flutter-登录token本地存储(shared_preferences)、路由拦截

App一般都会遇到这样的需求:没有登录则跳转登录页面,登录了则跳转至指定页面。

思路:

1.登录之后存储token。

2.路由拦截,没有登录则跳转至登录页面,登录了则跳转至指定页面。

步骤:

一:首先在pubspec.yaml中添加shared_preferences依赖库

shared_preferences: ^2.0.17

整个pubspec.yaml如下所示:

name: flutter_doctor_app
description: A new Flutter application.

# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.19.2 <3.0.0"

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  shared_preferences: ^2.0.17

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
     - images/info_image_portrait.png
     - images/nav_icon_back.png
     - images/logo.png
     - images/passwordinvisible.png
     - images/passwordvisible.png
     - images/weixin_icon.png
#     - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

二.在lib目录下创建common文件夹,创建LoginPrefs.dart文件

LoginPrefs.dart内容如下:

import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginPrefs{
  static const String USER_NAME="USER_NAME";//用户名
  static const String TOKEN="TOKEN";//token
  static  late SharedPreferences _prefs;//延迟初始化
  static Future<String> init() async {
    WidgetsFlutterBinding.ensureInitialized();
    _prefs = await SharedPreferences.getInstance();
    return 'ok';
  }
  static void saveUserName(String userName) {
    _prefs.setString(USER_NAME, userName);
  }
  static String? getUserName() {
    return _prefs.getString(USER_NAME);
  }
  static void saveToken(String token){
    _prefs.setString(TOKEN, token);
  }
  static String? getToken() {
    return _prefs.getString(TOKEN);
  }
  static void removeUserName() {
    _prefs.remove(USER_NAME);
  }
  static void removeToken() {
    _prefs.remove(TOKEN);
  }
  static void clearLogin(){
    _prefs.clear();
  }
}

三.在lib目录的common文件夹下创建MyRoutes.dart文件

MyRoutes.dart内容如下:

//配置路由

import 'package:flutter/material.dart';
import 'package:flutter_doctor_app/common/LoginPrefs.dart';
import '../login.dart';
import '../main.dart';

/*
 *  这个方法是固定写法,功能就像是一个拦截器。
 */
Route<dynamic>? onGenerateRoute(RouteSettings settings) {
  Map<String, Widget> routes = {
    'home': MyHomePage(), //定义app路径
    'login': LoginPage(), //定义login路径
  };

  String routerName = routeBeforeHook(settings);
  bool mathMap = false;
  Route<dynamic>? mathWidget;
  routes.forEach((key, v) {
    if (key == routerName) {
      mathMap = true;
      mathWidget = MaterialPageRoute(builder: (BuildContext context) => v);
    }
  });

  if (mathMap) {
    return mathWidget;
  }
  return MaterialPageRoute(
      builder: (BuildContext context) => Container(
            child: Text('404'),
          ));
}

String routeBeforeHook(RouteSettings settings) {
  if(checkToken()==false){
    return 'login';
  }else{
    return settings.name!;
  }
}
bool checkToken() {
  String token = LoginPrefs.getToken()??'';
  if ('' != token) return true;
    return false;
}

四.在main.dart中修改main方法如下所示:

void main() async{
  String value= await LoginPrefs.init();// await 关键字必须用在异步方法中 await等待异步方法执行完毕 异步方法必须用变量接收
  if('ok'==value){
    runApp(MyApp());
  }
}

shared_preferences的初始化过程是个耗时的操作,所以要放在异步方法中,LoginPrefs.dart的init()方法

static Future<String> init() async {

WidgetsFlutterBinding.ensureInitialized();

_prefs = await SharedPreferences.getInstance();

return 'ok';

}

我们需要的是必须要等待初始化完成,我们才可以进行其它操作,所以前面需要await修饰,等待异步初始化完成,而若使用await关键字则必须在异步方法中,所以,修改main方法由async修饰。

void main() async{

String value= await LoginPrefs.init();// await 关键字必须用在异步方法中 await等待异步方法执行完毕 异步方法必须用变量接收

if('ok'==value){

runApp(MyApp());

}

}

五.main.dart添加路由拦截

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      //去除右上角的Debug标签
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: createMaterialColor(Color(0xFF009999)),
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      initialRoute: "home",
      onGenerateRoute: onGenerateRoute,
      //注册路由表
    );
  }
}

onGenerateRoute: onGenerateRoute

路由拦截

六.login.dart中点击登录按钮执行的方法:

  void onLoginClick() async {
    print("登录");
    setState(() {
      // 当所有编辑框都失去焦点时键盘就会收起
      _uNameFocusNode.unfocus();
      _uPassFocusNode.unfocus();
      LoginPrefs.saveToken(_uNameController.text);//保存token (我这里保存的输入框中输入的值)
      Navigator.of(context).pop();//登录页消失
      Navigator.pushNamed(context, 'home');//跳转至首页
    });
  }

至此,就完成了路由拦截功能,没有登录则跳转登录页面,登录了则跳转至指定页面。

猜你喜欢

转载自blog.csdn.net/Jushuzhan/article/details/129002931