如何在Flutter应用程序中保存上次打开的屏幕 [英] How to save last opened screen in flutter app

查看:87
本文介绍了如何在Flutter应用程序中保存上次打开的屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在引导后重新打开上次打开的屏幕,是否有任何简单的方法?欢迎示例代码!

I am trying to reopen last opened screen after boot, Is there any simple way to do so ? sample codes are welcome !

到目前为止,我尝试使用 SharedPreferences 编写一个代码(我到某处了)。

So far I tried a code(which I got somewhere) with SharedPreferences, but it's not working.

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!'),
        ),
      ),
    );
  }
}

我应该使用 SQLite JSON 代替 SharedPreferences 来简化代码?谢谢。

should I use SQLite or JSON instead of SharedPreferences to make the code simple? thanks.

推荐答案

演示



Demo

实际上,当我们在应用程序内的不同屏幕之间导航时,路线堆栈正在改变。

when we are navigating through different screens within app, actually, the route stacks are changing.

,首先,我们需要弄清楚如何收听此更改,例如推送屏幕,弹出回到用户屏幕。

So, firstly, we need to figure out how to listen to this changes e.g Push screen, Pop back to users screen.

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

we can actually put this on every navigation-related button.

<强>。抽屉上的物品

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

b。在标题栏后退按钮上

    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"),
        ),

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

Therefore, we will have more code and it will be harder to manage.

Flutter在MaterialApp上提供了一些 中间件来捕获路线堆栈上的更改。

Nonetheless, Flutter provides on MaterialApp, that we can have some "middleware" to capture those changes on route stacks.

我们可能在MyApp小部件上有此内容:

We may have this on our MyApp widget :

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 如下所示的类:

We can define MyRouteObserver class as below :

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方法,如下所示:

B. How to Start the App

As users interacting through the screens, the Shared Preferences will always store last route name. To make the app navigate correspondingly, we need to make our BaseScreen statefull and override its initState method as below :

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。工作仓库



您可以查看此存储库如上面第二个选项所述,它将覆盖RouteObserver

C. Working Repo

You may look at this repository that overrides RouteObserver as explained in second option above

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

Saving and Opening Screen Beta and Screen Delta in different starts

为简单起见,我建议使用共享首选项。因为我们只记录了简单的String作为路由名,所以我们只能将两行代码保存到Save中,并将两行代码写入Load。

I suggest to use Shared preferences for simplicity. As we only record simple String for route name, we can only write two lines of code to Save and two lines of code to Load.

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

If we use JSON file, we need to manually set Path for it using path_provider package.

此外,如果使用SQLite,则需要进行设置数据库(可能包括多于8行),设置表以及插入表的方法。

Moreover, if we use SQLite, we need to setup DB (may consist > 8 more lines), and setup table and also inserting table method.

这篇关于如何在Flutter应用程序中保存上次打开的屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆