我們知道flutter框架中有StatefulWidget
的存在辖所,而它對(duì)應(yīng)的State
有自己的一套生命周期磨德。具體可查閱State生命周期。它并不能完全滿足類似iOS中UIViewController生命周期的需求酥宴。慶幸的是RouteObserver
這個(gè)類可以幫我們實(shí)現(xiàn)您觉。
RouteObserver
詳解本篇文章就不說了,網(wǎng)上資料一大把肆糕。但是RouteObserver
使用起來比較繁瑣在孝,每一個(gè)需要監(jiān)聽路由變化的Widget
都需要去實(shí)現(xiàn)接口RouteAware
。并重寫didChangeDependencies
方法(在其中添加訂閱消息的代碼)和dispose
方法(在其中取消訂閱)私沮。
所以我將這個(gè)功能封裝成了一個(gè)Widget:CWRouteListenWidget
仔燕,使用起來非常方便,只需在build
方法中涨享,將你需要監(jiān)聽的Widget作為CWRouteListenWidget
的子Widget即可厕隧。
示例代碼如下:
-
首先在創(chuàng)建
MaterialApp
的地方注冊(cè)navigatorObservers
在需要監(jiān)聽的widget中使用:
class TempPage extends StatelessWidget {
const TempPage({Key? key}) : super(key: key);
void _appear(CWRouteChangeType type) {
switch (type) {
case CWRouteChangeType.push:
debugPrint("從其他頁面push到當(dāng)前頁面");
break;
case CWRouteChangeType.pop:
debugPrint("從其他頁面返回到當(dāng)前頁面");
break;
}
}
void _disappear(CWRouteChangeType type) {
switch (type) {
case CWRouteChangeType.push:
debugPrint("從當(dāng)前頁面push到其他頁面");
break;
case CWRouteChangeType.pop:
debugPrint("從當(dāng)前頁面返回到其他頁面");
break;
}
}
@override
Widget build(BuildContext context) {
return CWRouteListenWidget(
appearHandler: _appear,
disappearHandler: _disappear,
child: Scaffold(
appBar: AppBar(
title: const Text("test"),
),
body: const Center(
child: Text("content"),
),
),
);
}
}
- 其中
appearHandler
類似iOS中的viewWillAppear||viewDidAppear
- 其中
disappearHandler
類似iOS中的viewWillDisappear||viewDidDisappear
CWRouteListenWidget
源碼如下:
import 'package:flutter/material.dart';
// 路由操作枚舉
enum CWRouteChangeType {
push,
pop
}
// 路由監(jiān)聽widget
class CWRouteListenWidget extends StatefulWidget {
static RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
final Widget child;
// 當(dāng)前頁面展示時(shí)的回調(diào)
final Function(CWRouteChangeType)? appearHandler;
// 當(dāng)前頁面消失時(shí)的回調(diào)
final Function(CWRouteChangeType)? disappearHandler;
// 構(gòu)造方法
const CWRouteListenWidget({Key? key, required this.child, this.appearHandler, this.disappearHandler}) : super(key: key);
@override
_CWRouteListenWidgetState createState() => _CWRouteListenWidgetState();
}
class _CWRouteListenWidgetState extends State<CWRouteListenWidget> with RouteAware {
@override
void didChangeDependencies() {
ModalRoute? route = ModalRoute.of(context);
if (route != null) {
CWRouteListenWidget.routeObserver.unsubscribe(this);
// 注冊(cè)監(jiān)聽
CWRouteListenWidget.routeObserver.subscribe(this, route as PageRoute);
}
super.didChangeDependencies();
}
@override
void dispose() {
// 移除監(jiān)聽
CWRouteListenWidget.routeObserver.unsubscribe(this);
super.dispose();
}
@override
void didPush() {
if (widget.appearHandler != null) {
widget.appearHandler!(CWRouteChangeType.push);
}
super.didPush();
}
@override
void didPop() {
if (widget.disappearHandler != null) {
widget.disappearHandler!(CWRouteChangeType.pop);
}
super.didPop();
}
@override
void didPushNext() {
if (widget.disappearHandler != null) {
widget.disappearHandler!(CWRouteChangeType.push);
}
super.didPushNext();
}
@override
void didPopNext() {
if (widget.appearHandler != null) {
widget.appearHandler!(CWRouteChangeType.pop);
}
super.didPopNext();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}