如何在 Widget 构建方法中调用异步属性 [英] How do I call async property in Widget build method

查看:42
本文介绍了如何在 Widget 构建方法中调用异步属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

推荐答案

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

<小时>

一般来说,当使用 FutureBuilderFutures 时,你必须记住,封闭的小部件可以随时重建(例如,因为设备被旋转,或显示键盘).这意味着再次调用 build 方法.


In general, when using FutureBuilder or Futures, 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.

在这种特殊情况下,这不是问题,因为插件缓存值并立即返回它,但一般来说,您永远不应该在 buildFuture> 方法.相反,从 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 构建方法中调用异步属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆