##
前言:
在原生的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)
![image](https://upload-images.jianshu.io/upload_images/6865547-2751f061ff0fbde3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在项目里面的pubspec.yaml 添加依赖 然后在项目根目录打开控制台输入 flutter pub get 命令回去下载相对应的依赖
## 2具体实现
先实现登录界面的功能
![image](https://upload-images.jianshu.io/upload_images/6865547-8fa5f96a22ee14a1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
登录页面是两个输入框TextFiled 和一个RaisedButton 来实现请求后台来处理登录功能
通过Dio库来实现异步网络请求 然后 通过 factory BackBean.fromJson 来转换成对象
在登录成功后通过 SharedPreferences 来储存数据 如下图所示 在登录成功后调用sharedPreferences.setString ()方法来存数据
![image](https://upload-images.jianshu.io/upload_images/6865547-fd21e1e89d1e7467.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
### 下面是登录页面的具体实现
```
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();
},)
) }, )],
); }
}
```
### 欢迎页(闪屏页面)的具体实现
![image](https://upload-images.jianshu.io/upload_images/6865547-b5058492fef61188.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image](https://upload-images.jianshu.io/upload_images/6865547-745c677a7ee1a208.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在initState 初始化生命周期方法里面 我们做一个3秒钟的倒计时 3秒钟 后我们调用toLogin方法 在login方法里面 我们 做了处理 调用
sharedPreferences.getString('password');来读取缓存的里面的数据 做空判 如果没有缓存数据我们就去登陆页面 如果有数据我们之间调用
登陆接口 进行自动登录操作 登录完成后我们直接跳转到主页 欢迎页的具体代码实现 如下
![image](https://upload-images.jianshu.io/upload_images/6865547-694cc5acd8493dfc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
具体代码 (欢迎页面)
```
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类来 转换就行了
![image](https://upload-images.jianshu.io/upload_images/6865547-9b9fce85ed9e1c50.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 最后总结 :
我也是个初学 flutter 的新手 希望我平时写的一些基础功能能够帮助到大家,有兴趣的同学可以私下研究下。这里就不过多讲了 最后希望我的文章能帮助到各位解决问题 ,以后我还会贡献更多有用的代码分享给大家。有兴趣的同学麻烦给关注和star 也可以加我个人QQ/微信(1693891473)
## QQ交流群