简介
GetView不适合做基类,所以考虑模仿其写法,自己写一个页面基类。
需要修改的地方
tag需要作为一个变量,在构造页面的时候由外部传入。
命名调整一下,我们的工程中页面习惯叫page,逻辑习惯叫logic。所以,controller的名字修改为logic
一直想用Get.put()来得到logic的实例。但是Flutter Dart的反射功能不完善,所以从类型T得到T的实例有困难。由于这个原因,还是参考GetView的做法,采用Get.find()来获取logic的实例。
T get logic => GetInstance().find<T>(tag: tag);
绑定函数Get.put()如果让调用者处理,那么我在跳转页面的时候,不但要知道哪个页面,还要知道哪个logic,感觉不是很合理。所以,最后决定在构造函数中执行这个绑定函数(page的子类)。
界面更新放弃Obs方式,固定使用update()方式;所以在build函数中固定包一层GetBuilder();这样就避免了页面不更新的尴尬。
基类添加abstract关键字,防止实例化,这个很好,借鉴过来。
鉴于页面大多使用Scaffold骨架,所以把这个也写进去,然后分为标题,body什么的让子类重写。
abstract class BasePage<T extends GetxController> extends StatelessWidget {
const BasePage({super.key, this.tag});
final String? tag;
T get logic => GetInstance().find<T>(tag: tag);
@override
Widget build(BuildContext context) {
return GetBuilder<T>(
tag: tag,
builder: (_) {
return _buildInternal();
},
);
}
Widget _buildInternal() {
return GBScaffold(
title: title,
body: buildBody(),
actions: buildActions(),
bottom: buildBottom(),
);
}
final String title = "";
Widget buildBody() {
return Container();
}
List<Widget>? buildActions() {
return null;
}
PreferredSizeWidget? buildBottom() {
return null;
}
}
使用的例子
- 比如购物车,我们首先写一个继承自GetxController的logic
class CartLogic extends GetxController {
}
- 再写一个继承自BasePage的Page
class CartPage extends BasePage<CartLogic> {
CartPage({super.key, super.tag}) {
Get.put(CartLogic(), tag: tag);
}
@override
String get title => "tab_cart".tr;
@override
Widget buildBody() {
return Column(
children: [
messageRow(),
logic.dataList.isNotEmpty
? Expanded(child: listWidget())
: Expanded(
child: Kong(
img: R.assetsImgKongNocontent,
title: logic.dataReady ? 'cart_empty_tip'.tr : "",
)),
operatorWidget(),
],
);
}
}
绑定函数Get.put(CartLogic(), tag: tag)在构造函数中执行,只执行一次
大多数情况,重写title和body就可以了,进行具体的页面布局。在Page中,要访问CartLogic的成员,直接使用logic.就可以了。基类BasePage使用了Get.find()来得到这个实例。这样就保证了put()和find()方法的对应,避免了put()方法的遗漏。
等Flutter Dart良好支持反射的时候,将put()方法移到基类BasePage中就更好了。
页面如何跳转?
可以将页面跳转封装成一个独立的方法,方便调用。由于购物车需要logic和view的对应,所以考虑用时间戳作为tag,保证不会重复,避免出现多个Page对应同一个logic的情况。
/// 打开购物车页面
static void openCart() {
String tag = 'cart${DateTime.now().microsecondsSinceEpoch}';
Get.to(() => CartPage(tag: tag));
}