在日常移动开发中,很多时候需要我们添加一个加载中间页,即加载中,加载失败,加载重试,加载完成等功能,这样可以避免在无网或者弱网情况下,导致无法加载完整UI界面,这样的影响是非常不好的。
本篇文章将记录如果封装一个统一的加载中间页。
在文章开始之前,我们先来写一个枚举,用来定义三个加载状态,即加载中,加载成功,加载失败
enum ViewState { loading, done, error }
新建一个 LoadingStateWidget 继承自StatelessWidget ,根据我们的需要的大致需求,我们需要接收一个child,一个当前加载状态,一个返回参数,即加载失败,重新加载的retry 方法。
final ViewState viewState;
final VoidCallback retry;
final Widget child;
接下来就是业务代码
我这里加载中,直接使用了系统的转圈组件CircularProgressIndicator,当然,这个组件是可以自定义的哦
// 加载中Widget get _loadingView {return const Center(child: CircularProgressIndicator(),);}
加载失败的时候需要展示的界面,在这里,一般都会加一个重试的按钮,具体的功能,可以根据需求去绘制界面功能
// 加载失败Widget get _errorView {return Center(child: Column());}
完整代码如下:
enum ViewState { loading, done, error }class LoadingStateWidget extends StatelessWidget {final ViewState viewState;final VoidCallback retry;final Widget child;const LoadingStateWidget({Key? key,this.viewState = ViewState.loading,required this.retry,required this.child}): super(key: key);@overrideWidget build(BuildContext context) {if (viewState == ViewState.loading) {return _loadingView;}if (viewState == ViewState.error) {return _errorView;} else {return child;}}// 加载中Widget get _loadingView {return const Center(child: CircularProgressIndicator(),);}// 加载失败Widget get _errorView {return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Image.asset("assets/images/ic_error.png",width: 100,height: 100,),const Padding(padding: EdgeInsets.only(top: 8),child: Text(TigerString.net_request_fail,style: TextStyle(fontSize: 18,color: Colors.red,),),),Padding(padding: const EdgeInsets.only(top: 8,),child: OutlinedButton(onPressed: retry,style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.white),overlayColor: MaterialStateProperty.all(Colors.black12),),child: const Text(TigerString.reload_again,style: TextStyle(color: Colors.black87,),),),),],),);}
}
使用方法如下:
传入三个参数,加载的延时任务,当前加载状态,及加载完成后需要展示的child
LoadingStateWidget(retry: model.getData,viewState: model.viewState,child: HomePageWidget.bodyWidget(model),
)
我这里的加载refresh 方法,直接使用的是一个延时加载的模拟方式
getData() async {if(viewState == ViewState.error){viewState = ViewState.loading;notifyListeners();}await Future.delayed(Duration(seconds: 5));viewState = ViewState.error;notifyListeners();
}
总体内容比较简单,代码量也没有多少,个人觉得没什么值得浪费大量语言来描述,看一下运行结果:
记得之前看到一个大佬说过这么一句话,在flutter 中,只有你使用的widget 够多,就没有完成不了的界面,请问你是怎么看待这句话呢?评论区告诉我哦!!!