我们知道flutter框架中有StatefulWidget
的存在,而它对应的State
有自己的一套生命周期。具体可查阅State生命周期。它并不能完全满足类似iOS中UIViewController生命周期的需求。庆幸的是RouteObserver
这个类可以帮我们实现。
RouteObserver
详解本篇文章就不说了,网上资料一大把。但是RouteObserver
使用起来比较繁琐,每一个需要监听路由变化的Widget
都需要去实现接口RouteAware
。并重写didChangeDependencies
方法(在其中添加订阅消息的代码)和dispose
方法(在其中取消订阅)。
所以我将这个功能封装成了一个Widget:CWRouteListenWidget
,使用起来非常方便,只需在build
方法中,将你需要监听的Widget作为CWRouteListenWidget
的子Widget即可。
示例代码如下:
-
首先在创建
MaterialApp
的地方注册navigatorObservers
在需要监听的widget中使用:
class TempPage extends StatelessWidget {
const TempPage({Key? key}) : super(key: key);
void _appear(CWRouteChangeType type) {
switch (type) {
case CWRouteChangeType.push:
debugPrint("从其他页面push到当前页面");
break;
case CWRouteChangeType.pop:
debugPrint("从其他页面返回到当前页面");
break;
}
}
void _disappear(CWRouteChangeType type) {
switch (type) {
case CWRouteChangeType.push:
debugPrint("从当前页面push到其他页面");
break;
case CWRouteChangeType.pop:
debugPrint("从当前页面返回到其他页面");
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
}
// 路由监听widget
class CWRouteListenWidget extends StatefulWidget {
static RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
final Widget child;
// 当前页面展示时的回调
final Function(CWRouteChangeType)? appearHandler;
// 当前页面消失时的回调
final Function(CWRouteChangeType)? disappearHandler;
// 构造方法
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);
// 注册监听
CWRouteListenWidget.routeObserver.subscribe(this, route as PageRoute);
}
super.didChangeDependencies();
}
@override
void dispose() {
// 移除监听
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;
}
}