当前位置:网站首页>The solution that flutterweb browser cannot be rolled back after refreshing
The solution that flutterweb browser cannot be rolled back after refreshing
2022-07-06 17:41:00 【Code is not difficult to write】
problem
stay Flutter Developed web page runtime , After the browser refreshes the web page , Although the page before refresh will be displayed ( The premise is to jump with static route ), But then call Navigator.pop The method cannot go back to the previous page , Including clicking the back button of the browser is also invalid ( In the address bar url Will change , The page won't change ).
reason
When the browser refreshes ,Flutter The engine will restart , And load the current page , in other words , After refreshing Flutter All static variables in memory are initialized , The previous page records in the page stack are not preserved , Only the current page . It's like browsing the web , Copy out the URL of one page , Open the new tab again .
Solution
( One ) Ideas
Know what caused it , Solve the problem pertinently . Page stack record missing , Then maintain a backup stack in the code , Listen for page routing , Every time you enter a new page , Record the current page URL, When you exit , Delete the recorded URL, When the browser refresh stack record fails , Help go back to the previous page .
( Two ) Advantages and disadvantages of the scheme
advantage : The fallback effect can be realized without exception , call Navigator.pop Method or clicking the browser fallback button ;
shortcoming : Navigator.pushName().then The callback for cannot take effect , Because it is the previous page regenerated , So the callback is not called ; The temporary data in the page after fallback will disappear , For example, the contents in the input box , Member variables, etc ; The jump must be in the form of static routing , And pass the reference to Uri The parcel , You cannot pass arguments with a constructor .
Realization
1. Web Local storage tools —localStorage
localStorage Is in html It's a bag window A storage object in , With key、value Storage in the form of
// Guide pack
import 'dart:html' as html;
// Usage mode
html.window.localStorage["key"] = "value"
The encapsulation of storage tools will not be covered here , Encapsulate according to the business situation , Just call it easily .
2. Stack recording tool class RouterHistory
This is a stack recording tool , The main function is to register and listen , Add or delete records, etc .
/// DB() For encapsulated local databases
class RouterHistory {
/// Listen for callback before browser refresh
static Function(html.Event event)? _beforeUnload;
/// Listen for the callback when the browser fallback
static Function(html.Event event)? _popState;
/// Whether the current page has been refreshed
static bool isRefresh = false;
/// Initialize and register listening
static void register() {
// Callback on refresh
_beforeUnload = (event) {
// Local records , Marked as " Refreshed "
DB(DBKey.isRefresh).value = true;
// Remove the listening of the instance before refreshing
html.window.removeEventListener('beforeunload', _beforeUnload);
html.window.removeEventListener('popstate', _popState);
};
// Browser fallback button callback
_popState = (event) {
// The page is refreshed , Trigger standby callback
if (isRefresh) {
_back(R.currentContext); //R.currentContext For the current page Context
}
};
// Add listening
html.window.addEventListener('beforeunload', _beforeUnload);
html.window.addEventListener('popstate', _popState);
// Fetch from local database " Refresh " Mark
isRefresh = DB(DBKey.isRefresh).get(false);
// If not refreshed , Clear the history in the last standby stack
if (!isRefresh) {
clean();
}
// Restore the refresh mark in the local library
DB(DBKey.isRefresh).value = false;
}
static bool checkBack(currentContext) {
// Whether it can work normally pop
if (Navigator.canPop(currentContext)) {
return true;
}
// If not, enable the alternate stack
_back(currentContext);
return false;
}
// return
static void _back(currentContext) {
List history = get();
if (history.length > 1) {
history.removeLast();
set(history);
// Jump to the previous page and close the current page
Navigator.of(currentContext).popAndPushNamed(history.last);
}
}
// Add records
static add(String? path) {
if (path == null) return;
List history = get();
if (history.contains(path)) return;
history.add(path);
set(history);
}
// Delete record
static remove(String? path) {
if (path == null) return;
List history = get();
history.remove(path);
set(history);
}
// Set alternate stack data
static String set(List<dynamic> history) => DB(DBKey.history).value = json.encode(history);
// Fetch the spare stack data
static get() => json.decode(DB(DBKey.history).get('[]'));
// Clear alternate stack
static clean() => DB(DBKey.history).value = '[]';
}
3. monitor Flutter route
Custom class and implement NavigatorObserver, And put the implementation class in MaterialApp Medium navigatorObservers Parameters in .
// Implementation class
class HistoryObs extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
// Save routing information
RouterHistory.add(route.settings.name);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
// Delete routing information
RouterHistory.remove(route.settings.name);
}
}
// Set listening
MaterialApp(
......
navigatorObservers: [ HistoryObs() ],
......
)
4. Routing method encapsulation
The jump method must be a static route , To ensure that the parameters and paths can be in url in , To achieve the fallback effect
/// Replace Navigator.pop ,
static pop() {
// Check whether it can return normally , If not, return FALSE
if (RouterHistory.checkBack(currentContext)) {
Navigator.pop(currentContext);
}
}
/// Static route jump
static Future toName(String pageName, {Map<String, dynamic>? params}) {
// Package path and parameters
var uri = Uri(scheme: RoutePath.scheme, host: pageName, queryParameters: params ?? {});
return Navigator.of(currentContext).pushNamed(uri.toString());
}
5. Initialization position
Put it in MaterialApp The outer build in , or initState Then you can .
@override
void initState() {
super.initState();
RouterHistory.register();
}
@override
Widget build(BuildContext context) {
// or RouterHistory.register();
return MaterialApp(
navigatorObservers: [MiddleWare()],
);
}
The above is the key code of the scheme
Last
This solution can only solve the problem , But not the best solution . If there is a better solution, please leave a message ~
Flutter Official Navigator 2.0 Although it can achieve fallback , In essence, it also jumps to a new page , And cause confusion in stack records , Not like real web equally , Interested students can learn about Navigator 2.0.
Navigator2.0 In the processing of the browser Back button, it is similar to Navigator1.0 Different , When you click the back button Navigator2.0 It's not execution pop operation , But to perform setNewRoutePath operation , In essence, it should be from the browser history For the previous page url, Then reload . This really solves the problem of fallback after refresh , Because the browser after refresh history Not lost , But it also led to what we mentioned in the article flutter Page stack confusion in .
If you lack direction on your way to advancement , You can scan the QR code below to join our circle and learn and communicate with Android developers !
- All the following contents can be obtained on wechat !
Android Advanced learning complete manual
Android On the ali P7 Learning video
BATJ Big factory Android High frequency interview questions
author : Su Boman
link :https://juejin.cn/post/7114848130004156446
边栏推荐
- Re signal writeup
- The most complete tcpdump and Wireshark packet capturing practice in the whole network
- Pyspark operator processing spatial data full parsing (4): let's talk about spatial operations first
- Flink parsing (III): memory management
- Binary search strategy
- PySpark算子处理空间数据全解析(5): 如何在PySpark里面使用空间运算接口
- TCP连接不止用TCP协议沟通
- [VNCTF 2022]ezmath wp
- Hongmeng introduction and development environment construction
- 应用服务配置器(定时,数据库备份,文件备份,异地备份)
猜你喜欢
【逆向中级】跃跃欲试
Huawei certified cloud computing hica
Grafana 9 正式发布,更易用,更酷炫了!
JUnit unit test
轻量级计划服务工具研发与实践
pip install pyodbc : ERROR: Command errored out with exit status 1
[ASM] introduction and use of bytecode operation classwriter class
PyTorch 提取中间层特征?
The problem of "syntax error" when uipath executes insert statement is solved
The NTFS format converter (convert.exe) is missing from the current system
随机推荐
CTF逆向入门题——掷骰子
虚拟机启动提示Probing EDD (edd=off to disable)错误
02个人研发的产品及推广-短信平台
Connect to LAN MySQL
CTF reverse entry question - dice
[rapid environment construction] openharmony 10 minute tutorial (cub pie)
Virtual machine startup prompt probing EDD (edd=off to disable) error
yarn : 无法加载文件 D:\ProgramFiles\nodejs\yarn.ps1,因为在此系统上禁止运行脚本
Xin'an Second Edition: Chapter 25 mobile application security requirements analysis and security protection engineering learning notes
Summary of study notes for 2022 soft exam information security engineer preparation
BearPi-HM_ Nano development board "flower protector" case
Unity小技巧 - 绘制瞄准准心
03个人研发的产品及推广-计划服务配置器V3.0
C# WinForm中DataGridView单元格显示图片
Automatic operation and maintenance sharp weapon ansible Playbook
04个人研发的产品及推广-数据推送工具
【Elastic】Elastic缺少xpack无法创建模板 unknown setting index.lifecycle.name index.lifecycle.rollover_alias
Detailed explanation of data types of MySQL columns
自动化运维利器ansible基础
自动化运维利器-Ansible-Playbook