flutter 通过用户信息配置路由拦截 shared_preferences

 环境:

flutter  sdk

  [√] Flutter (Channel stable, 2.2.3, on Microsoft Windows [Version 10.0.19042.1110], locale zh-CN)

shared_preferences  缓存

  shared_preferences: ^2.0.6

文件目录   类似vue的目录

common 存放全局的用户信息

 Global.dart

//
// http请求配置
// 1107949255@qq.com
// ただ爽子のFANだけど
//

import 'package:shared_preferences/shared_preferences.dart';

class Global {
  static SharedPreferences _prefs;

  //初始化全局信息,会在APP启动时执行
  static Future<String> init() async {
    if (_prefs == null) {
      _prefs = await SharedPreferences.getInstance();

    }
    return 'ok';
  }

  get token {
    print(_prefs);
    return _prefs.getString('token');
  }

  set token(value) {
    _prefs.setString("token", value);
  }

  get username {
    print(_prefs);
    return _prefs.getString('username');
  }

  set username(value) {
    _prefs.setString("username", value);
  }

  get nickname {
    print(_prefs);
    return _prefs.getString('nickname');
  }

  set nickname(value) {
    _prefs.setString("nickname", value);
  }
}

定义了几个set get方法, 直接用过new  Global().token 获取信息。

routers 存放路由文件  

index.dart 配置路由信息

//
// http请求配置
// 1107949255@qq.com
// ただ爽子のFANだけど
//
import 'package:flutter/material.dart';
import 'dart:core';
import '../views/app.dart';
import '../views/derivative/goods/goods.dart';
import '../views/derivative/singles/singles.dart';
import '../views/user/login.dart';
import '../views/user/photos.dart';
import '../views/user/userCenter.dart';
import '../views/derivative/map/map.dart';
import '../views/loading.dart';
import '../common/Global.dart';

// 钩子函数获取token信息
routeBeforeHook(RouteSettings settings) {
  /// Global.prefs 是全局的 SharedPreferences 实例
  /// SharedPreferences 是常用的本地存储的插件
  if (settings.name == '/loading' || settings.name == '/login')
    return settings.name;
  if (checkToken() == false) {
    return '/login';
  } else {
    return settings.name;
  }
}

checkToken() {
  var globalClass = new Global();
  bool isHaveToken = false;
  isHaveToken = globalClass.token !=null && globalClass.token != '' ? true : false;
  return isHaveToken;
}

// 路由配置
Route<dynamic> onGenerateRoute(RouteSettings setting) {
  Map<String, Widget> routes = {
    '/app': new App(page: 0), //定义app路径
    '/goods': new Goods(), //定义goods路径
    '/singles': new Singles(), //定义goods_item路径
    '/login': new MyLogin(), //定义login路径
    '/photos': new MyPthotos(), //定义photos路径
    '/map': new MyMap(), //定义map路径
    '/uc': new UC(), //定义用户中心路径
    '/loading': new LoadingPage(), // 加载页面
  };

  String routerName = routeBeforeHook(setting);
  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'),
          ));
}

修改main.dart 

//
// http请求配置
// 1107949255@qq.com
// ただ爽子のFANだけど
//
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'store/app_state.dart';
import 'routers/index.dart' as router;  // 引入router
import "common/Global.dart";
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  SharedPreferences.setMockInitialValues({});   // 处理报错
  Store<AppState> store = new Store<AppState>(mainReducer,
      initialState: new AppState(
        auth: new AuthState(),
      ));

//  Global.init().then((e) => runApp(MyApp(store: store)));
//  Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
  WidgetsFlutterBinding.ensureInitialized(); //解决加载json错误
  Global.init().then((dynamic res) {
    print(res);
    if (res == 'ok') {
      runApp(MyApp(store: store));
    }
  });
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  final Store store;
  MyApp({this.store});

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store, //绑定store
        child: MaterialApp(
          debugShowCheckedModeBanner: false, //去除右上角的Debug标签
          title: '君に届け',
          onGenerateRoute: router.onGenerateRoute,  // 显示router
          theme: pinkTheme,
          initialRoute: "/loading",
        ));
  }
}

// 定义一个喜欢的主题
final ThemeData pinkTheme = new ThemeData(
    primaryColor: Colors.pink[200],
    primaryColorBrightness: Brightness.light,
    backgroundColor: Colors.amberAccent);

演示:

默认进入页为loading页

 点击关闭时默认进入主页,如下

onPressed: () {
              // 进入主页
                  Navigator.of(context).pushReplacementNamed("/app");
}));

但是加了路由验证之后,就会进入 routeBeforeHook 钩子函数里面,类似vue,判断用户信息(token)是否存在,存在就进入,否则就直接跳转到登录页(或者说直接加载登录页)

输入用户名、密码后,需要保存全局token、username、nickname,直接赋值

var globalClass = new Global();
globalClass.username = username.text;
globalClass.token = "dwq1d1123";
globalClass.nickname = "ただ爽子のFANだけど";

然后就跳到了中心页


import 'package:shared_preferences/shared_preferences.dart';
// 获取用户信息
Future<Object> getUserInfo() async { Map userInfo =
new Map(); SharedPreferences prefs = await SharedPreferences.getInstance(); var userName = prefs.getString('username'); var nickName = prefs.getString('nickname'); userInfo["username"] = userName; userInfo["nickname"] = nickName; return userInfo; } // 显示username nickename child: FutureBuilder<Object>( future: getUserInfo(), initialData: {}, builder: (BuildContext context, AsyncSnapshot snapshot) { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ new Text( snapshot.data["username"] == null ? '未登录' : snapshot.data["username"], style: TextStyle( fontSize: 18.0, color: Color(0xFF353535), ), ), new Text( (snapshot.data["nickname"] == null ? '' : snapshot.data["nickname"]), style: TextStyle( fontSize: 14.0, color: Color(0xFFa9a9a9), ), ), ]); }),

之后再怎么跳转路由都是ok的,但是当你清除缓存信息后

logout(context) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.remove('username'); //删除指定键
    prefs.remove('token'); //删除指定键
//    print('注销成功');
    Navigator.pushNamed(context, '/login');
  }

后面再操作也会跳到登录页。

 

 对于这些问题,网络上的解决方法都是寥寥可数,要不就是copy过去copy过来,看的头疼,我也是不断地尝试,各种升级测试,才勉强搞出的解决办法,真希望有详细的文档。希望flutter后面越来越完善,ღ( ´・ᴗ・` )比心。

今ならできます。
原文地址:https://www.cnblogs.com/shuangzikun/p/flutter_router_userinfo.html