在Dart中,处理异步有两种方式,一种方式是asyn/awiat ,另外一种方式就是FutureBuilder,FutureBuilder可以在网络请求开始前,请求中,请求完成or失败,帮助咱们管理咱们的UI界面。github
///构造方法以及对应参数类型 const FutureBuilder({ Key key, this.future, this.initialData, @required this.builder, }) : assert(builder != null), super(key: key); final Future<T> future; //获取数据异步操做 final AsyncWidgetBuilder<T> builder;//根据状态返回不一样widget ///ConnectionState四种状态 enum ConnectionState { /// Not currently connected to any asynchronous computation. /// For example, a [FutureBuilder] whose [FutureBuilder.future] is null. none, /// Connected to an asynchronous computation and awaiting interaction. waiting, /// Connected to an active asynchronous computation. /// For example, a [Stream] that has returned at least one value, but is not /// yet done. active, /// Connected to a terminated asynchronous computation. done, } 复制代码
FutureBuilder( future: fetchPost(),//网络请求操做 builder: (BuildContext context, AsyncSnapshot<CommonModel> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return Text("Input a url to connect"); case ConnectionState.waiting: //圆形加载widget return Center(child: CircularProgressIndicator()); case ConnectionState.active: return Text(""); case ConnectionState.done: if (snapshot.hasError) { return Text( "${snapshot.error}", style: TextStyle(color: Colors.red), ); } else { //正常数据返回回调 return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( "网络数据返回", style: TextStyle(fontSize: 20), ), Text("title:${snapshot.data.title}"), Text("icon:${snapshot.data.icon}"), Text("url:${snapshot.data.url}"), ], ); } } }) 复制代码
接下来开始咱们的通用网络Widget封装,根据Demo咱们发现须要一个能够返回Future网络请求方法,加载界面Widget,加载出错的Widgwt以及网络请求结束正常展现数据Widget。编程
框架思考须要实现功能:json
1.定义传递请求方法redux
///FutureBuilder的future传的内容 typedef LoadDataFuture<T> = Future<T> Function(BuildContext context); 复制代码
2.定义抽象类(数据正常展现Widget)markdown
abstract class NetNormalWidget<T> extends StatelessWidget { final T bean;//通用数据类 NetNormalWidget({this.bean}); @override Widget build(BuildContext context) { return buildContainer(bean); } ///给定义Widget赋值 Widget buildContainer(T t); } 复制代码
3.定义网络出错Widget以及对应点击回调网络
///net出错 回调 abstract class ErrorCallback { void retryCall(); } ///网络请求 失败 Widget class NetErrorWidget extends StatelessWidget { final Widget errorChild; final ErrorCallback callback; NetErrorWidget({@required this.errorChild, this.callback}); @override Widget build(BuildContext context) { return GestureDetector( child: errorChild, onTap: () => callback?.retryCall(), ); } } 复制代码
4.开始拼装框架app
///定义该框架须要属性实现对应State class FutureBuilderWidget<T> extends StatefulWidget { final Widget loadingWidget; final Widget errorWidget; final NetNormalWidget<T> commonWidget; final LoadDataFuture<T> loadData; FutureBuilderWidget( {@required this.commonWidget, @required this.loadData, this.loadingWidget, this.errorWidget}); @override State<StatefulWidget> createState() => _FutureBuilderWidgetState<T>(); } ///实现State方法并mixins网络出错点击回调 class _FutureBuilderWidgetState<T> extends State<FutureBuilderWidget<T>> with ErrorCallback { @override void initState() { super.initState(); widget.loadData(context); } ///默认加载界面 final defaultLoading = Center( child: CircularProgressIndicator(), ); ///默认出错界面 Widget _defaultError(dynamic error) { return Center( child: Text(error.toString()), ); } @override Widget build(BuildContext context) { return FutureBuilder( future: widget.loadData(context), builder: (BuildContext context, AsyncSnapshot<T> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: break; case ConnectionState.waiting: case ConnectionState.active: return widget.loadingWidget ?? defaultLoading; case ConnectionState.done: if (snapshot.hasError) { ///网络出错 if (widget.errorWidget != null) { ///自定义出错界面 if (widget.errorWidget is NetErrorWidget) { return widget.errorWidget; } else { ///只自定义界面显示内容 return NetErrorWidget( errorChild: widget.errorWidget, callback: this, ); } } else { ///选用默认出错界面 return NetErrorWidget( errorChild: _defaultError(snapshot.error), callback: this, ); } } return widget.commonWidget.buildContainer(snapshot.data); } }); } @override void retryCall() { widget.loadData(context); setState(() { ///通知State从新构建界面须要 }); } } 复制代码
class FutureBuilderDemo extends StatefulWidget { @override State<StatefulWidget> createState() => _FutureBuilderState(); } class _FutureBuilderState extends State<FutureBuilderDemo> with ErrorCallback{ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("FutureBuilder控件封装"), ), body: FutureBuilderWidget<CommonModel>( commonWidget: CommonWidget(), loadData: _loadData, //自定义出错界面以及对应店家回调事件(本例子直接关闭界面) // errorWidget: NetErrorWidget( // callback:this, // errorChild: Center( // child: Text("网络出错 点击返回"), // ), // ), ), ); } ///网络请求库 Future<CommonModel> _loadData(BuildContext context) async { Api.baseUrl = 'http://www.devio.org/io/flutter_app/'; final resp = await HttpUtil.instance.fetchGet('json/test_common_model.json'); return CommonModel.fromJson(resp); } @override void retryCall() { Navigator.of(context).pop(); } } ///实现抽象方法,直接给界面复制 class CommonWidget extends NetNormalWidget<CommonModel> { @override Widget buildContainer(CommonModel t) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text(t.title), Text(t.icon), ], ), ); } } 复制代码