如何在Widget构建方法中调用async属性 [英] how do i call async property in Widget build method
问题描述
我是Flutter和Dart的新手,我正在尝试构建一个Flutter应用,该应用在屏幕上显示设备信息。为此,我正在尝试使用以下库:'device_info',来自此处: https ://pub.dartlang.org/packages/device_info#-readme-tab-
I'm new to Flutter and Dart, and I'm trying to build a Flutter app which displays the device information on the screen. For this purpose I'm trying to use this library: 'device_info' from here: https://pub.dartlang.org/packages/device_info#-readme-tab-
在MyApp类的'build'方法中,我是尝试从 device_info包实例化该对象并调用恰好是异步属性的属性。由于默认的构建方法不是异步的,如何在构建方法中调用此属性?以下是我的代码:
In the 'build' method of the MyApp class, I am trying to instantiate the object from 'device_info' package and call a property which happens to be an async property. Since the default build method is not asynchronous, how do I call this property in the build method? Following is my code:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
AndroidDeviceInfo androidDeviceInfo = await deviceInfoPlugin.androidInfo;
return MaterialApp(
title: 'My Device Info',
home: Scaffold(
appBar: AppBar(
title: Text('My Device Info'),
),
body: Center(
child: Text('Device model:' + 'Moto'),
),
),
);
}
}
推荐答案
I建议您使用 FutureBuilder
:
import 'package:flutter/material.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// save in the state for caching!
DeviceInfoPlugin _deviceInfoPlugin;
@override
void initState() {
super.initState();
_deviceInfoPlugin = DeviceInfoPlugin();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Device Info',
home: Scaffold(
appBar: AppBar(
title: Text('My Device Info'),
),
body: FutureBuilder<AndroidDeviceInfo>(
future: _deviceInfoPlugin.androidInfo,
builder: (BuildContext context, AsyncSnapshot<AndroidDeviceInfo> snapshot) {
if (!snapshot.hasData) {
// while data is loading:
return Center(
child: CircularProgressIndicator(),
);
} else {
// data loaded:
final androidDeviceInfo = snapshot.data;
return Center(
child: Text('Android version: ${androidDeviceInfo.version}'),
);
}
},
),
),
);
}
}
通常,使用 FutureBuilder
或 Future
s时,请记住可以在以下位置重建封闭的小部件任何时候(例如由于设备旋转或显示键盘)。也就是说,再次调用 build
方法。
In general, when using FutureBuilder
or Future
s, you have to keep in mind that the enclosing widget can be rebuilt at any time (e.g. because the device was rotated, or the keyboard is shown). That means the build
method is called again.
在这种特殊情况下,这不是问题,因为插件会缓存值并立即返回它,但一般来说,绝对不要在 build
方法内部创建或获取 Future
。而是从 initState
或单击事件处理程序执行此操作:
In this particular case it's not a problem because the plugin caches the value and returns it instantly, but in general you should NEVER create or get a Future
inside of the build
method. Instead, do it from initState
or a click event handler:
import 'package:flutter/material.dart';
class FooWidget extends StatefulWidget {
@override
_FooWidgetState createState() => _FooWidgetState();
}
class _FooWidgetState extends State<FooWidget> {
Future<int> _bar;
@override
void initState() {
super.initState();
_bar = doSomeLongRunningCalculation();
}
void _retry() {
setState(() {
_bar = doSomeLongRunningCalculation();
});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
FutureBuilder<int>(
future: _bar,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasData) {
return Text('The answer to everything is ${snapshot.data}');
} else {
return Text('Calculating answer...');
}
},
),
RaisedButton(
onPressed: _retry,
child: Text('Retry'),
)
],
);
}
}
Future<int> doSomeLongRunningCalculation() async {
await Future.delayed(Duration(seconds: 5)); // wait 5 sec
return 42;
}
这篇关于如何在Widget构建方法中调用async属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!