2020.10.20日更新:
最近發(fā)現(xiàn)了一種更好的方法店雅,就是使用RouteAware監(jiān)聽路由养叛,下面是實(shí)現(xiàn)代碼
初始化:
RouteObserver需要申明為全局屬性并作為參數(shù)傳入MaterialApp中
static final RouteObserver<PageRoute> routeObserver = RouteObserver();
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorObservers: [AppRoutesManager.routeObserver],
...
);
}
使用
abstract class BaseState<T extends StatefulWidget, E extends BaseViewModel> extends State<T> with RouteAware {
String pageName;
E viewModel;
void initState() {
super.initState();
}
@override
void didChangeDependencies() {
AppRoutesManager.routeObserver.subscribe(this, ModalRoute.of(context)); //訂閱
super.didChangeDependencies();
print("didChangeDependencies: ${pageName}界面");
}
@override
void didPush() {
debugPrint("------> didPush-進(jìn)入${pageName}");
super.didPush();
}
@override
void didPop() {
debugPrint("------> didPop離開${pageName}");
super.didPop();
}
@override
void didPopNext() {
debugPrint("------> didPopNext-進(jìn)入${pageName}");
super.didPopNext();
}
@override
void didPushNext() {
debugPrint("------> didPushNext-${pageName}進(jìn)入下一個(gè)界面");
super.didPushNext();
}
@override
void dispose() {
AppRoutesManager.routeObserver.unsubscribe(this); //取消訂閱
super.dispose();
// print("dispose 離開${pageName}界面");
print("銷毀${pageName}界面");
}
但是這個(gè)方法有一定的缺陷:
1,AlertView,showGeneralDialog等彈出框里面push的路由沒有辦法監(jiān)聽,我的解決辦法是是寫一個(gè)回調(diào)函數(shù)來(lái)讓主界面來(lái)處理路由的push鬓照;
2,當(dāng)使用PageView做界面切換時(shí)孤紧,監(jiān)聽也是不生效的豺裆,這個(gè)時(shí)候需要自己手動(dòng)調(diào)用RouteAware里面的函數(shù)。
下面是之前的實(shí)現(xiàn)方法:
之前項(xiàng)目集成了友盟統(tǒng)計(jì)的功能坛芽,發(fā)現(xiàn)flutter界面統(tǒng)計(jì)無(wú)法實(shí)現(xiàn)留储,在iOS中我們可以通過(guò)Controller的生命周期中的viewWillAppear:來(lái)處理什么時(shí)候進(jìn)入界面viewWillDisappear:來(lái)處理什么時(shí)候來(lái)開界面,離開界面的處理咙轩,flutter的組件雖然也有生命周期获讳,但是它的生命周期不足以支持我們準(zhǔn)確的統(tǒng)計(jì),雖然我們可以用initState做進(jìn)入的的邏輯活喊,用dispose做離開的邏輯丐膝,但是initState 只有在組件第一次初始化的時(shí)候跳用,dispose只有在組件銷毀的時(shí)候才會(huì)調(diào)用钾菊;當(dāng)我們使用Navigator.push離開當(dāng)前界面進(jìn)入下一個(gè)界面時(shí)我們沒有辦法做處理帅矗,當(dāng)然我們也可以選擇在每一個(gè)push的地方做處理,但是這樣就會(huì)出現(xiàn)大量的重復(fù)代碼煞烫,顯然不符合我們的初衷浑此,經(jīng)過(guò)思考我給出了下面這個(gè)方案:
1,寫一個(gè)基類BaseState繼承自State滞详,其中有一個(gè)參數(shù)pageName
abstract class BaseState<T extends StatefulWidget> extends State {
String pageName;
void initState() {
// TODO: implement initState
super.initState();
print("initState 進(jìn)入${pageName}界面");
FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
}
@override
Widget build(BuildContext context) {
return build(context);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
print("dispose 離開${pageName}界面");
print("銷毀${pageName}界面");
FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
}
}
2,實(shí)現(xiàn)一個(gè)push函數(shù),做統(tǒng)一的界面跳轉(zhuǎn),利用Future的特性做界面的離開凛俱,進(jìn)入邏輯處理:
//跳轉(zhuǎn)界面
void push({Widget page, Function popCallback}) {
print("push: 離開${pageName}界面");
FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
return page;
})).then((data) {
print("pop 進(jìn)入${pageName}界面");
FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
if (popCallback != null) {
popCallback(data);
}
});
}
//路由跳轉(zhuǎn)
void routerPush({String route, Function popCallback}) {
print("routerPush: 離開${pageName}界面");
FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
AppRoutesManager.router.navigateTo(context, route).then((data) {
print("pop 進(jìn)入${pageName}界面");
FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
if (popCallback != null) {
popCallback(data);
}
});
}
使用:
class MinePage extends StatefulWidget {
@override
_MinePageState createState() => _MinePageState();
}
class _MinePageState extends BaseState<MinePage> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
void initState() {
// TODO: implement initState
pageName = "個(gè)人中心";
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: pageName,
),
body: GestureDetector(
onTap: () {
routerPush(route: AppRoutesManager.mall, popCallback: (data) {});
},
child: Container(
color: Colors.red,
),
),
);
}
}
注:如果是安卓的話可以通過(guò)initState(), deactivate()加一個(gè)bool類型的參數(shù)處理紊馏,不知道為什么iOS端的deactivate()函數(shù)在push下一個(gè)界面的時(shí)候不調(diào)用。