Flutter页面resume返回时如何重新调用initState刷新服务端数据
initState 只会在StatefulWidget第一次插入组件树的时候由框架自动调用,你通过Navigator.push跳转新页面时,上一页面会一直保留在路由栈中不会被销毁,pop返回时自然不会重新触发initState。不要手动强行调用initState,这个方法是框架生命周期调度的核心方法,手动调用很容易引发上下文未就绪、状态重复绑定等异常。
你只需要把写在initState里的服务端拉数逻辑抽成独立可复用的方法,在路由返回的时机调用即可,以下是两种常用实现:
方案1:await 路由Future(单页面场景首选,代码量最小无侵入)
Navigator.push本身会返回一个Future对象,新页面pop出栈时这个Future就会执行完成,你只需要在跳转时加await等待,返回后直接调用拉数方法就行:// 修改你的跳转代码 // 可以接收新页面pop时传回的参数,判断是否需要刷新 final needRefresh = await Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, animation2) => Directionality( textDirection: TextDirection.rtl, child: screen, ), ), ); // 新页面返回后会走到这里,判断需要刷新就调用拉数逻辑 if (needRefresh == true) { _fetchServerData(); // 你从initState里抽出来的拉数据方法 }如果需要新页面触发特定操作后才让上一页刷新,只需要在新页面pop的时候传参即可:
// 新页面中执行返回时,传入true告知上一页需要刷新 Navigator.pop(context, true);如果不需要判断条件,只要从当前页返回就刷新,直接省略参数判断,await结束后直接调用拉数方法即可。
方案2:RouteObserver全局路由监听(适合多页面统一管控场景)
如果项目中有大量页面需要实现返回刷新的逻辑,可以用Flutter内置的RouteObserver做全局路由订阅,给需要监听的页面注册路由回调,当监听到当前页面从后台回到前台(也就是其他页面pop返回)时,自动触发拉数逻辑。这种方式不需要修改每一处跳转代码,但是前期需要做全局配置,普通单页面场景优先选方案1即可。
避坑提醒:不要为了触发
initState就刻意把上一页从路由栈移除再重新push,这种做法会导致页面切换动画异常、路由栈逻辑混乱,额外的性能开销也很高,完全没有必要。
内容的提问来源于stack exchange,提问作者user19540440

