Search code examples
flutterdartstream-builder

How to redirect to another screen/page in Stream Builder after some seconds in FLUTTER?


I am taking data from the BLE device and using Stream Builder to get data. I want to jump to the next page i.e Homepage after getting value 1 from the BLE device after showing the gif for like 2 seconds. How can I achieve this?

My code is:

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,
                        ),
                      ),
                    ],
                  ),
                );
              }
            },
          )
        ],
      ),
    );
  }
}

I want something like this to be included in the code when the current value is 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,
      );
    });
  }

My screen shows this on current value other than 1:

enter image description here

and on value = 1 it should display this image and after 2 seconds it should navigate to Homepage:

enter image description here


Solution

  • You can use the Future.delayed method to delay the redirect to home page.

    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();
        },
      );
    }
    

    I made a snippet with two futures for demonstration, but you can change the first one to your StreamBuilder and it should work just as well.

    Delayed Redirect Demo:

    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();
                  },
                );
              },
            ),
          ),
        );
      }
    }