如何在 FLUTTER 几秒钟后重定向到 Stream Builder 中的另一个 screen/page?
How to redirect to another screen/page in Stream Builder after some seconds in FLUTTER?
我正在从 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:
在值 = 1 时它应该显示此图像,2 秒后它应该导航到主页:
您可以使用 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();
},
);
}
我制作了一个包含两个 futures 的片段用于演示,但您可以将第一个更改为您的 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();
},
);
},
),
),
);
}
}
我正在从 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:
在值 = 1 时它应该显示此图像,2 秒后它应该导航到主页:
您可以使用 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();
},
);
}
我制作了一个包含两个 futures 的片段用于演示,但您可以将第一个更改为您的 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();
},
);
},
),
),
);
}
}