我正在开发Flutter应用程序,但想知道从UI调用异步代码时应该怎么做-假设UI小部件的构建方法。
例如,我的应用程序通过服务类连接Firebase,该服务类使用Async- Await样式从Firebase抓取记录。使用await可确保我的服务类的方法在返回UI端之前将完成记录检索。
但是,由于服务类的方法被标记为异步,因此它将在服务类的方法完成之前立即将Future返回给调用UI小部件,并且UI代码保持运行。
是的,我可以为“ then()”回调编写代码以处理检索到的记录,但是小部件内随后的其他代码又取决于异步调用的结果呢?这是否意味着我需要将所有内容都嵌入“ then()”子句中,并避免在返回Future的方法调用之后添加任何执行步骤?对于这种使用模型有什么建议的模式吗?
@override Widget build(BuildContext context) { RealtimeDatabase.getData() // my service class .then((onValue) { ..... // do something after the async call is completed } ..... // do something immediately before the async call is done class RealtimeDatabase { Future<String> getData() async { DataSnapshot dataSnapshot = await FirebaseDatabase.instance.reference().orderByKey().once(); // will wait until completed ..... .....
抱歉,如果我的描述不够清楚,欢迎提供任何建议。
吉米
在Flutter中,有一些小部件可以帮助您无缝执行此操作(例如FutureBuilder,StreamBuilder),并且您可以根据其分辨率控制要呈现的内容。
FutureBuilder
StreamBuilder
范例FutureBuilder:
Widget build(BuildContext context) { return new FutureBuilder( future: FirebaseDatabase.instance.reference().child("node"), builder: (BuildContext context, AsyncSnapshot snapshot) { return snapshot.hasData? new Scaffold( ///start building your widget tree ):new CircularProgressIndicator(); ///load until snapshot.hasData resolves to true },); }
示例StreamBuilder:
class Database { DatabaseReference _refProfile = FirebaseDatabase.instance.reference().child( "profiles"); getProfiles() => _refProfile.onValue; }
.............
Widget build(BuildContext context) { return new StreamBuilder<Event>( stream: _database.getProfiles(), //_database = new Database() builder: (BuildContext context, AsyncSnapshot<Event> event) { return event.hasData?new Scaffold( ///build your widget tree ):new CircularProgressIndicator(); /// place holder }
值得一提的是
FutureBuilder如果您希望 一次 获取 一些数据并且不关心保持一致的连接或跟踪数据中的任何更改,则最好使用。 __
而StreamBuilder另一方面,通过,您可以继续收听数据,并且可以根据数据中的任何更新来更新UI的状态。