gpt4 book ai didi

flutter - 如何在flutter应用程序中保存上次打开的屏幕

转载 作者:行者123 更新时间:2023-12-03 02:45:00 25 4
gpt4 key购买 nike

我试图在启动后重新打开上次打开的屏幕,有什么简单的方法吗?欢迎提供示例代码!

到目前为止,我用 SharedPreferences 尝试了一个代码(我在某处找到了) ,但它不起作用。

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

String lastRouteKey = 'last_route';

void main() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
String lastRoute = preferences.getString(lastRouteKey);
runApp(MyApp(lastRoute));
}

class MyApp extends StatelessWidget {
final String lastRoute;

MyApp(this.lastRoute);

@override
Widget build(BuildContext context) {
bool hasLastRoute = getWidgetByRouteName(lastRoute) != null;

return MaterialApp(
home: Foo(),
initialRoute: hasLastRoute ? lastRoute : '/',
onGenerateRoute: (RouteSettings route) {
persistLastRoute(route.name);
return MaterialPageRoute(
builder: (context) => getWidgetByRouteName(route.name),
);
},
);
}

Widget getWidgetByRouteName(String routeName) {
switch (routeName) {
case '/':
return MainWidget();
case '/':
return SecondRoute();
// Put all your routes here.
default:
return null;
}
}

void persistLastRoute(String routeName) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setString(lastRouteKey, routeName);
}
}

class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Foo'),
),
body: Column(
children: <Widget>[
RaisedButton(
child: Text('Open route second'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),

RaisedButton(
child: Text('Open route main'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MainWidget()),
);
},
),
],
),
);
}
}

class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}

class MainWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("MainWidget"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}

我应该使用 SQLiteJSON而不是 SharedPreferences使代码简单?谢谢。

最佳答案

演示

Demo

A. 导航

当我们在应用程序内的不同屏幕中导航时,实际上,路由堆栈正在发生变化。

因此,首先,我们需要弄清楚如何收听这种变化,例如推送屏幕、弹出回用户屏幕。

1.在每个 Action 按钮中附加保存方法

我们实际上可以把它放在每个与导航相关的按钮上。

一种。关于抽屉元素

  ListTile(
title: Text("Beta"),
onTap: () {
saveLastScreen(); // saving to SharedPref here
Navigator.of(context).pushNamed('/beta'); // then push
},
),


湾标题栏后退按钮

    appBar: AppBar(
title: Text("Screen"),
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
saveLastScreen(); // saving to SharedPref here
Navigator.pop(context); // then pop
},
),
),

C。并在 Android 设备上捕获手机返回按钮的事件

  @override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: (){ // will triggered as we click back button
saveLastScreen(); // saving to SharedPref here
return Future.value(true);
},
child: Scaffold(
appBar: AppBar(
title: Text("Base Screen"),
),

因此,我们将拥有更多的代码并且更难管理。

2. 使用 Route observer 监听路由变化

尽管如此,Flutter 在 MaterialApp 上提供了一些“ middleware”来捕获路由堆栈上的这些变化。

我们可能在 MyApp 小部件上有这个:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Save Last Route',
navigatorObservers: <NavigatorObserver>[
MyRouteObserver(), // this will listen all changes
],
routes: {
'/': (context) {
return BaseScreen();
},
'/alpha': (context) {
return ScreenAlpha();
},

我们可以定义 MyRouteObserver类如下:

class MyRouteObserver extends RouteObserver {

void saveLastRoute(Route lastRoute) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('last_route', lastRoute.settings.name);
}

@override
void didPop(Route route, Route previousRoute) {
saveLastRoute(previousRoute); // note : take route name in stacks below
super.didPop(route, previousRoute);
}

@override
void didPush(Route route, Route previousRoute) {
saveLastRoute(route); // note : take new route name that just pushed
super.didPush(route, previousRoute);
}

@override
void didRemove(Route route, Route previousRoute) {
saveLastRoute(route);
super.didRemove(route, previousRoute);
}

@override
void didReplace({Route newRoute, Route oldRoute}) {
saveLastRoute(newRoute);
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
}
}

B. 如何启动应用程序

当用户通过屏幕进行交互时,共享首选项将始终存储最后的路线名称。为了使应用程序相应地导航,我们需要使我们的 BaseScreen 有状态并覆盖其 initState 方法,如下所示:

return MaterialApp(
routes: {
'/': (context) {
return BaseScreen(); // define it as Main Route
},

class BaseScreen extends StatefulWidget {
@override
_BaseScreenState createState() => _BaseScreenState();
}

class _BaseScreenState extends State<BaseScreen> {
@override
void initState() {
super.initState();
navigateToLastPage();
}

void navigateToLastPage() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String lastRoute = prefs.getString('last_route');
// No need to push to another screen, if the last route was root
if (lastRoute.isNotEmpty && lastRoute != '/') {
Navigator.of(context).pushNamed(lastRoute);
}
}


C. 工作 repo

你可以看看这个 repository覆盖 RouteObserver,如上面第二个选项中所述

在不同的开始保存和打开 Screen Beta 和 Screen Delta

D. 共享首选项/JSON/SQLite

为简单起见,我建议使用共享首选项 .由于我们只记录简单的路由名称String,所以我们只能写两行代码保存和两行代码加载。

如果我们使用 JSON 文件,我们需要使用 path_provider 手动为其设置 Path包裹。

此外,如果我们使用 SQLite,我们需要设置 DB(可能包含 > 8 行),以及设置表和插入表的方法。

关于flutter - 如何在flutter应用程序中保存上次打开的屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57537347/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com