如何在Widget构建方法中调用async属性

时间:2018-12-16 08:39:38

标签: dart flutter

我是Flutter和Dart的新手,我正在尝试构建一个Flutter应用,该应用在屏幕上显示设备信息。为此,我正在尝试使用以下库:'{_3}}

在MyApp类的'build'方法中,我试图从'device_info'包实例化该对象并调用恰好是异步属性的属性。由于默认的构建方法不是异步的,如何在构建方法中调用此属性?以下是我的代码:

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

3 个答案:

答案 0 :(得分:3)

我建议您使用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}'),
              );
            }
          },
        ),
      ),
    );
  }
}

通常,在使用FutureBuilderFuture时,请记住可以随时重新构建封闭的小部件(例如,因为设备已旋转或显示了键盘, )。这意味着build方法被再次调用。

在这种特殊情况下,这不是问题,因为该插件会缓存该值并立即返回它,但是通常,您永远不要在Future方法内创建或获取build。而是从initState或点击事件处理程序中进行操作:

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;
}

答案 1 :(得分:1)

您可以使用 await / async 来实现它(通过@GünterZöchbauer说,不需要根据最新版本的dart导入lib。)

并从构建方法中调用函数。

  _getAndroidDeviceInfo() async{
    AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
    print(androidInfo.device);
  }

   _get_iOS_DeviceInfo() async{
    IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
    print(iosDeviceInfo.model);
  }

答案 2 :(得分:1)

build()需要同步结果,因此在async中使用await / build()是不合适的。

在尚未获得异步结果的情况下,使用FutureBuilder返回占位符Container(),或者在出现以下情况时将异步代码移至initState()并使用setState更新状态该值可用于再次执行build