环境:
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后面越来越完善,ღ( ´・ᴗ・` )比心。