首页 > 解决方案 > 在 FLUTTER 中几秒钟后如何重定向到 Stream Builder 中的另一个屏幕/页面?

问题描述

我正在从 BLE 设备获取数据并使用 Stream Builder 获取数据。我想在显示 gif 2 秒后从 BLE 设备获取值 1 后跳转到下一页,即主页。我怎样才能做到这一点?

我的代码是:

import 'dart:typed_data';
import 'package:epicare/ConfigurationScreen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'Homepage.dart';

class ConfDeviceSet extends StatefulWidget {
  const ConfDeviceSet({Key key, this.device}) : super(key: key);
  final BluetoothDevice device;
  @override
  _ConfDeviceSetState createState() => _ConfDeviceSetState();
}

class _ConfDeviceSetState extends State<ConfDeviceSet> {
  // BLE
  final String SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
  //final String SERVICE_UUID = "0365a300-8d69-4066-80c7-554298a6ec5e";
  //final String CHARACTERISTIC_UUID = "cf01c075-cb75-4dea-819e-2a79dd466bcb";
  final String CHARACTERISTIC_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
  bool isReady;
  Stream<List<int>> stream;
  List<int> lastValue;
  List<double> traceDust = List();
  @override
  void initState() {
    isReady = false;
    discoverServices();
  }

  discoverServices() async {
    List<BluetoothService> services = await widget.device.discoverServices();
    services.forEach((service) {
      if (service.uuid.toString() == SERVICE_UUID) {
        service.characteristics.forEach((characteristic) {
          if (characteristic.uuid.toString() == CHARACTERISTIC_UUID) {
            characteristic.setNotifyValue(!characteristic.isNotifying);
            stream = characteristic.value;
            //print(stream);
            lastValue = characteristic.lastValue;
            //print(lastValue);

            setState(() {
              isReady = true;
            });
          }
        });
      }
    });
  }

  _dataParser(List<int> data) {
    var value = Uint8List.fromList(data);
    print("stream.value: $value"); // stream.value: [33]
    var hr = ByteData.sublistView(value, 0, 1);
    print("Calibration value: ${hr.getUint8(0)}");
    return hr.getUint8(0); // Heart rate: 33
  }

  void navigateScreen() {
    var d = Duration(seconds: 2);
    // delayed 5 seconds to next page
    Future.delayed(d, () {
      // to next page and close this page
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
          builder: (context) {
            return Homepage(device: widget.device);
          },
        ),
        (route) => false,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: const Color(0xffE5E0A1),
        elevation: 0,
        centerTitle: true,
        title: Text(
          "Configuration",
          style: TextStyle(
            fontSize: 15.0,
            color: Colors.black,
            fontFamily: 'Montserrat',
            fontWeight: FontWeight.normal,
          ),
        ),
        leading: IconButton(
          icon: Icon(
            Icons.arrow_back,
            color: Colors.black,
          ),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) {
                  return ConfigurationScreen(
                    device: widget.device,
                  );
                },
              ),
            );
          },
        ),
      ),
      body: Column(
        children: [
          StreamBuilder<List<int>>(
            stream: stream,
            initialData: lastValue,
            builder: (BuildContext context, AsyncSnapshot<List<int>> snapshot) {
              var currentValue = _dataParser(snapshot.data);
              if (currentValue == 1) {
                print("Test Conf 1");
                return Container(
                  padding: EdgeInsets.only(top: 65),
                  alignment: Alignment.center,
                  child: Column(
                    children: [
                      Text(
                        'Device Configured Successfully!',
                        style: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.w600,
                          fontSize: 15,
                          color: const Color(0xa8000000),
                          height: 1.3333333333333333,
                        ),
                        textHeightBehavior:
                            TextHeightBehavior(applyHeightToFirstAscent: false),
                        textAlign: TextAlign.center,
                      ),
                      Container(
                        padding: EdgeInsets.symmetric(vertical: 120),
                        child: Image.asset('assets/images/green-tick.gif'),
                      ),
                    ],
                  ),
                );
                navigateScreen();
              } else {

                return Container(
                  padding: EdgeInsets.only(top: 65),
                  alignment: Alignment.center,
                  child: Column(
                    children: [
                      Text(
                        'Device setting up...',
                        style: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.w600,
                          fontSize: 17,
                          color: const Color(0xa8000000),
                          height: 1.3333333333333333,
                        ),
                        textHeightBehavior:
                            TextHeightBehavior(applyHeightToFirstAscent: false),
                        textAlign: TextAlign.center,
                      ),
                      Container(
                        padding: EdgeInsets.symmetric(vertical: 120),
                        child: const SpinKitFadingCircle(
                          color: const Color(0xffF1C40E),
                          size: 200,
                        ),
                      ),
                    ],
                  ),
                );
              }
            },
          )
        ],
      ),
    );
  }
}

当当前值为 1 时,我希望在代码中包含这样的内容:

void navigateScreen()
  {
    var d = Duration(seconds: 2);
    // delayed 5 seconds to next page
    Future.delayed(d, () {
      // to next page and close this page
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
          builder: (context) {
            return Homepage(
                device: widget.device
            );
          },
        ),
            (route) => false,
      );
    });
  }

我的屏幕显示当前值不是 1:

在此处输入图像描述

在 value = 1 时,它应该显示此图像,并在 2 秒后导航到主页:

在此处输入图像描述

标签: flutterdartstream-builder

解决方案


您可以使用 Future.delayed 方法延迟重定向到主页。

if(currentValue == 1) {
  print("Test Conf 1");
  return FutureBuilder(
    future: Future.delayed(
      const Duration(seconds: 2),
      () {
        Navigator.pushAndRemoveUntil(
          context,
          MaterialPageRoute(
            builder: (context) {
              return Homepage(device: widget.device);
            },
          ),
          (route) => false,
        );
      },
    ),
    builder: (context, snapshot) {
      if (snapshot.connectionState != ConnectionState.done) {
        return Container(
          padding: const EdgeInsets.only(top: 65),
          alignment: Alignment.center,
          child: Column(
            children: [
              const Text(
                'Device Configured Successfully!',
                style: TextStyle(
                  fontFamily: 'Montserrat',
                  fontWeight: FontWeight.w600,
                  fontSize: 15,
                  color: Color(0xa8000000),
                  height: 1.3333333333333333,
                ),
                textHeightBehavior: TextHeightBehavior(
                    applyHeightToFirstAscent: false),
                textAlign: TextAlign.center,
              ),
              Container(
                padding: const EdgeInsets.symmetric(vertical: 120),
                child: Image.asset('assets/images/green-tick.gif'),
              ),
            ],
          ),
        );
      }
      return Container();
    },
  );
}

我制作了一个带有两个期货的片段进行演示,但是您可以将第一个更改为您的 StreamBuilder 并且它应该也可以正常工作。

延迟重定向演示:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Delayed Redirect',
      theme: ThemeData(primarySwatch: Colors.blue, brightness: Brightness.dark),
      initialRoute: "/setup",
      routes: {
        "/setup": (context) => const Setup(),
        "/home": (context) => const MyHomePage(),
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text("Home"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Icon(Icons.home),
            SizedBox(height: 15),
            Text("Home"),
          ],
        ),
      ),
    );
  }
}

class Setup extends StatelessWidget {
  const Setup({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text("Configuration"),
      ),
      body: Center(
        child: FutureBuilder(
          future: Future.delayed(
            const Duration(seconds: 2),
            () {
              return;
            },
          ),
          builder: (context, snapshot) {
            if (snapshot.connectionState != ConnectionState.done) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const [
                  CircularProgressIndicator(),
                  SizedBox(height: 15),
                  Text("Configuring Device..."),
                ],
              );
            }
            return FutureBuilder(
              future: Future.delayed(
                const Duration(seconds: 2),
                () {
                  Navigator.of(context).pushReplacementNamed("/home");
                },
              ),
              builder: (context, snapshot) {
                if (snapshot.connectionState != ConnectionState.done) {
                  return Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: const [
                      Icon(Icons.check),
                      SizedBox(height: 15),
                      Text("Device Configured Successfully!"),
                    ],
                  );
                }
                return Container();
              },
            );
          },
        ),
      ),
    );
  }
}

推荐阅读