前言:
? 在原生的andriod 和iOS app里面都會有自動登錄的功能 今天我就用flutter 來給大家實現雙端的自動登錄功能?
Android 端用的是 Sharedpreferences? 來實現對于輕量級數據的緩存 , IOS端 通常使用NSUserDefaults 來實現輕量級數據的緩存?
但是在flutter 有基于Android? iOS? 做支持的三方插件庫? shared_preferences???
1準備工作?
需要用的三方庫
shared_preferences: ^0.5.3+4? (緩存數據)
dio: 2.1.0? (網絡請求)
toast: ^0.1.5? (吐司文字類比 Android里面的toast)

在項目里面的pubspec.yaml? 添加依賴?? 然后在項目根目錄打開控制臺輸入 flutter?? pub get? 命令回去下載相對應的依賴
2具體實現
先實現登錄界面的功能

登錄頁面是兩個輸入框TextFiled? 和一個RaisedButton 來實現請求后臺來處理登錄功能
通過Dio庫來實現異步網絡請求? 然后? 通過? factory BackBean.fromJson 來轉換成對象
在登錄成功后通過 SharedPreferences? 來儲存數據 如下圖所示? 在登錄成功后調用sharedPreferences.setString ()方法來存數據

下面是登錄頁面的具體實現??
```
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:dio/dio.dart';
import 'tabs/Api.dart';
import 'entity/BackBean.dart';
import 'utils/ToastUtil.dart';
import 'Register.dart';
import 'My.dart';
/**
* 創建人:xuqing
* 創建時間:2019年12月22日19:28:56
* 類說明: 登錄頁面? 業務需求通過 dio 網絡請求庫 和 shared_preferences? 數據緩存庫 來實現自動登錄功能*
*/
class Loginextends StatefulWidget {
? Login({Key key}) :super(key: key);
? ? @override
? ? ? _LoginStatecreateState() {
? ? ? return _LoginState();
? }
}
class _LoginStateextends State {
? ? @override
? ? ? void initState() {
? ? ? super.initState();
? }
? @override
? ? void dispose() {
? super.dispose();
? }
? @override
? Widgetbuild(BuildContext context) {
// TODO: implement build
? ? return Scaffold(
? ? ? ? appBar:AppBar(
? ? ? ? title:Text("登錄"),?),
? ?? ? body:Layout(),
? ? );
? }
}
class Layoutextends StatefulWidget {
Layout({Key key}) :super(key: key);
? @override
? _LayoutStatecreateState() {
? ? return _LayoutState();
? }
}
class _LayoutStateextends State {
? ? var _username="";
? ? var _password="";
? ? @override
? void initState() {
? super.initState();
? }
@override
? void dispose() {
? super.dispose();
}
@override
? Widgetbuild(BuildContext context) {
// TODO: implement build
? ? return Column(
? ? ? ? children: [
? ? ? ? ? TextField(
? ? ? ? ? obscureText:false,
? ? ? ? ? ? decoration:InputDecoration(
? ? ? ? ? ? hintText:"請輸入賬號",
? ? ? ? ? ? ),
? ? ? ? ? ? onChanged: (value){
? ? ? ? setState(() {
? ? ? ? this._username=value;
?? ? ? ? });
? ?? ? },
? ),
? SizedBox(height:20,),
? ? ?? TextField(
? ? ? obscureText:true,
? ? ? decoration:InputDecoration(
? ? ? hintText:"請輸入密碼",
? ? ? ? ? ),
? ? ? ? ? onChanged: (value){
? ? ? ? setState(() {
? ? this._password=value;
? ? ? ? ? }); ?
},
),
Container(
? ? ? ? ? width:300,
? ? ? ? ? child:RaisedButton(
? ? ? ? ? child:Text("登錄"),
? ? ? ? ? ? color: Colors.blue,
? ? ? ? ? ? onPressed: ()async{
? ? ? ? ? ? Dio dio =new Dio();
? ? ? ? ? ? ? Response res=await? dio.get(Api.LOGIN_URL,
? ? ? ? ? ? ? ? ? queryParameters: {"username":_username,
? ? ? ? ? ? ? ? ? ? "password":_password});
? ? ? ? ? ? ? BackBean _backbean=BackBean.fromJson(res.data);
? ? ? ? ? ? ? String getmsg=_backbean.msg;
? ? ? ? ? ? ? int? getcode=_backbean.code;
? ? ? ? ? ? ? print(getmsg);
? ? ? ? ? ? ? print(getcode);
? ? ? ? ? ? ? if(getcode==200){
? ? ? ? ? ? ? //? print("登錄成功");
? ? ? ? ? ? ? ? SharedPreferences sharedPreferences =await SharedPreferences.getInstance();
? ? ? ? ? ? ? ? sharedPreferences.setString('username', _username);
? ? ? ? ? ? ? ? sharedPreferences.setString('password', _password);
? ? ? ? ? ? ? ? ToastUtil.showinfo(context, getmsg);
? ? ? ? ? ? ? ? Navigator.of(context).push(
? ? ? ? ? ? new MaterialPageRoute(builder: (context) {
? ? ? ? ? ? ? //指定跳轉的頁面
? ? ? ? ? ? ? ? ? ? ? return new My();
? ? ?? ?? },)
? ? ? );
? }else{
? ? ? ToastUtil.showinfo(context, getmsg);
? ? }
? ? print(res.data.toString());
? ? ?? },
? ? ),
?? ),
? ? ? ? RaisedButton(
? ? child:Text("注冊賬號"),
? ? ? ? ? color: Colors.red,
? ? ? ? ? textColor: Colors.white,
? ? ? ? ? onPressed: (){
? ? Navigator.of(context).push(
? ? new MaterialPageRoute(builder: (context) {
? ? ? //指定跳轉的頁面
? ? ? ? ? ? ? ? ? return new Register();
? ? ? ? ? ? ? ? },)
? ? ? ) }, )],
? ? );? }
}
```
### 歡迎頁(閃屏頁面)的具體實現


在initState 初始化生命周期方法里面 我們做一個3秒鐘的倒計時? 3秒鐘 后我們調用toLogin方法? 在login方法里面 我們 做了處理 調用
sharedPreferences.getString('password');來讀取緩存的里面的數據? 做空判 如果沒有緩存數據我們就去登陸頁面 如果有數據我們之間調用
登陸接口 進行自動登錄操作 登錄完成后我們直接跳轉到主頁? 歡迎頁的具體代碼實現? 如下

具體代碼 (歡迎頁面)
```
import 'package:flutter/material.dart';
import 'Login.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:dio/dio.dart';
import 'utils/StingUtil.dart';
import 'tabs/Api.dart';
import 'entity/BackBean.dart';
import 'utils/ToastUtil.dart';
import 'dart:async';
import 'My.dart';
void main() => runApp(MyApp());
class MyAppextends StatelessWidget {
// This widget is the root of your application.
? @override
? Widgetbuild(BuildContext context) {
return MaterialApp(
? ? home:Scaffold(
? ? appBar:AppBar(
? title:Text("歡迎頁"),? ),
? ?body:MyHomePage(),? )
? ? ? );
? ? }
}
/**
*
* 歡迎頁面*
*/
class MyHomePageextends StatefulWidget {
MyHomePage({Key key}) :super(key: key);
? @override
? _MyHomePageStatecreateState() {
return _MyHomePageState();
? }
}
class _MyHomePageStateextends State {
var _getaname="";
? var? _getpsw="";
? @override
? void initState() {
super.initState();
? ? int count =0;
? ? const period =const Duration(seconds:1);
? ? print('currentTime='+DateTime.now().toString());
? ? Timer.periodic(period, (timer) {
//到時回調
? ? ? print('afterTimer='+DateTime.now().toString());
? ? ? count++;
? ? ? if (count >=3) {
//取消定時器,避免無限回調
? ? ? ? timer.cancel();
? ? ? ? timer =null;
? ? ? ? toLoing();
? ? ? }
});
? }
@override
? void dispose() {
super.dispose();
? }
void? toLoing()async{
SharedPreferences sharedPreferences =await SharedPreferences.getInstance();
? ? _getaname = sharedPreferences.getString('username');
? ? _getpsw = sharedPreferences.getString('password');
? ? if(!StringUtil.isEmpty(_getaname)&&!StringUtil.isEmpty(_getpsw)){
Dio dio =new Dio();
? ? ? Response res=await dio.get(Api.LOGIN_URL, queryParameters: {"username":_getaname, "password":_getpsw});
? ? ? BackBean _backbean=BackBean.fromJson(res.data);
? ? ? String getmsg=_backbean.msg;
? ? ? int? getcode=_backbean.code;
? ? ? if(getcode==200){
ToastUtil.showinfo(context, getmsg);
? ? ? ? Navigator.of(context).push(
new MaterialPageRoute(builder: (context) {
return new My();
? ? ? ? ? ? },)
);
? ? ? }
}else{
Navigator.of(context).push(
new MaterialPageRoute(builder: (context) {
return new Login ();
? ? ? ? ? },)? );
? ? }
}
@override
? Widgetbuild(BuildContext context) {
// TODO: implement build
? ? return? Container(
? ? child:Image.network("http://pic1.win4000.com/mobile/2019-05-31/5cf0dd648a143.jpg"),
? ? );
? }
}
```
其他你自己要跳轉的主頁? 可以自己去拓展? 這個demo的請求接口是自己用spring boot 實現的 最后也會附上代碼鏈接地址
## 技術要點:
? 代碼相對簡單,思路也不復雜 會原生開發的同學應該很難容易看懂? 基本跟Android 的Sharedpreferences?? 用法類似 但是flutter? 在使用Shared_Preferences? 插件庫的時候 因為用了 await? 關鍵字 所有必須是在異步的方法 (async )里面進行實現 存儲和獲取數據? ,其次就是json 解析也相對簡單 在拿到res.data 直接通過? BackBean _backbean=BackBean.fromJson(res.data);來轉成對象操作 我們只需要創建如圖的bean類來 轉換就行了

## 最后總結? :
? 我也是個初學 flutter 的新手? 希望我平時寫的一些基礎功能能夠幫助到大家,有興趣的同學可以私下研究下。這里就不過多講了 最后希望我的文章能幫助到各位解決問題 ,以后我還會貢獻更多有用的代碼分享給大家。有興趣的同學麻煩給關注和star?