在Android 中可以定义Activity基类,所有可以在基类定义一些公共方法,比如全局标题栏,页面跳转动画,那么子啊FLutter中是不是也可以定义一个页面的基类,今天就来尝试一下。
首先我们定义一个抽象类BaseWidget,该类继承自StatefulWidget,代码如下:
abstract class BaseWidget extends StatefulWidget {
@override
BaseWidgetState createState() => getState();
BaseWidgetState getState();
}
上面的这个BaseWidgetState就是我们下面要定义的抽象类了,继承自State<T>,这里要传一个继承自BaseWidget的泛型,参考系统提供的StatefulWidget和State用发,我们之所以要定义两个抽象类,是要将他们两个关联起来。
abstract class BaseWidgetState<T extends BaseWidget> extends State<T> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
}
}
这里我们首先定义一个 initData();方法,用来初始化数据的,子类实现该方法即可,不需要在实现initState()方法
@override
void initState() {
super.initState();
initData();
}
然后我们在buid()方法中用Scaffold组件构建基类的页面框架:
Widget navigationBar; //navigationBar
Widget appBarWidget; //body
Widget endDrawerWidget;
@override
Widget build(BuildContext context) {
baseBean = getBaseBean();
return Scaffold(
appBar: appBarWidget, //顶部导航栏
endDrawer: endDrawerWidget, //右滑菜单栏
body: initBody(), //页面主体
bottomNavigationBar: navigationBar, //底部导航栏
);
}
这里为什么我将appBarWidget,endDrawerWidget,navigationBar定义成属性,但是却将页面主体定义成方法呢,因为在Flutter中定义为属性是可以不需要实现的,但是定义方法的话就必须实现,页面主体肯定是每个页面必不可少的,所以在这里定义为方法,其他的可以不需要所以定义为属性。
一般页面肯定会有网络请求,我们在Android 中一般都会将页面加载状态,空页面,加载失败等页面状态,统一管理的,那么在Flutter中应该怎么办呢,这里我大概讲一下我的方法,
Widget loadingWidget(Widget widget, BaseBean baseBean) {
if (baseBean.state == ViewState.loading) {
//页面默认为加载状态,展示加载页面
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Padding(padding: EdgeInsets.only(top: 30), child: Text("数据加载中。。。。"))
]);
} else if (baseBean.state == ViewState.empty) {
//当页面状态为空的时候,展示空页面
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 30), child: Text("很抱歉!没有数据"))
]);
} else if (baseBean.state == ViewState.error) {
//当接口返回错误状态是,页面展示错误页面
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 30), child: Text("很抱歉!出错了"))
]);
} else {
return widget;
}
这里定义了一个loadingWidget页面状态管理的方法,需要两个参数,第一个是接口请求成功后,展示的正确页面的组件widget,第二个是定义的一个状态管理的实体类,这个实体类很简单,就一个用枚举记录的页面状态,
这里要注意的是,所有的用来解析网络请求数据的实体类都必须继承这这个状态的实体类,实际上就是在所有接口返回中新增了一个记录页面状态的参数baseBean.state,我们在loadingWidget方法中根据页面状态来动态设置不同的状态页面。
现在我们来看看具体用法:
///继承自BaseWidget
class ArticleListWidget extends BaseWidget {
@override
BaseWidgetState<BaseWidget> getState() => ArticleListState();
}
///继承自BaseWidgetState
class ArticleListState extends BaseWidgetState<ArticleListWidget> {
///重写appBarWidget属性定义appBar
@override
Widget get appBarWidget => AppBar(title: Text("文章列表"));
///重写buildBody,返回页面主体
@override
Widget buildBody() {
return ArticleListBaseWidget(cid: 0);
}
///初始话数据方法,如果有接口请求可以在此初始化
@override
initData() {
}
}
网友评论