Flutter 如何使用共享首选项让用户保持登录状态?

Flutter 如何使用共享首选项让用户保持登录状态?,flutter,Flutter,我想在用户成功登录Flatter后保持用户登录。 我正在使用RESTAPI检索用户的用户名和密码。但我想保存这些详细信息,以便用户可以保持登录状态。我目前的情况是,我可以成功登录用户,但当我重新启动应用程序时,我必须再次登录,因此我需要将用户的详细信息保存在共享首选项中,以便用户可以在整个会话中保持登录状态,直到注销。但我无法做到这一点,请帮助我。 提前谢谢 这是我登录页面的代码。 我已经删除了应该在listview中的UI内容,因为这些内容并不相关 Login.dart import 'dar

我想在用户成功登录Flatter后保持用户登录。 我正在使用RESTAPI检索用户的用户名和密码。但我想保存这些详细信息,以便用户可以保持登录状态。我目前的情况是,我可以成功登录用户,但当我重新启动应用程序时,我必须再次登录,因此我需要将用户的详细信息保存在共享首选项中,以便用户可以在整个会话中保持登录状态,直到注销。但我无法做到这一点,请帮助我。 提前谢谢

这是我登录页面的代码。 我已经删除了应该在listview中的UI内容,因为这些内容并不相关

Login.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:restaurant_app/globalVar.dart';
import 'package:restaurant_app/homescreen.dart';
import 'package:restaurant_app/models/auth.dart';
import 'package:restaurant_app/signup.dart';
import 'package:http/http.dart' as http;
import 'package:restaurant_app/utils/authutils.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SignIn extends StatefulWidget {

    SignIn({ Key key, this.post }): super(key: key);

@override
_SignInState createState() => _SignInState();
    }

class _SignInState extends State<SignIn> with SingleTickerProviderStateMixin 
    {
    TabController controller;
    TextEditingController _email = new TextEditingController();
    TextEditingController _password = new TextEditingController();
    bool loading;

    final GlobalKey < ScaffoldState > _scaffoldKey = new GlobalKey<ScaffoldState>
        ();

    @override
    void initState() {
        // TODO: implement initState
        super.initState();
        _fetchSessionAndNavigate();
        controller = new TabController(length: 2, vsync: this);
        loading = false;
    }

    @override
    void dispose() {
        // TODO: implement dispose
        super.dispose();
        controller.dispose();
        setState(() {
            loading = false;
        });
        _email.dispose();
        _password.dispose();
    }

    final GlobalKey < FormState > _formKey = GlobalKey<FormState>();
    bool _autoValidate = false;

    _login(username, password) async {
        setState(() {
            loading = true;
        });

        var body = json.encode({
            "username": username,
            "password": password,
        });

        Map < String, String > headers = {
            'Content-type': 'application/json',
                'Accept': 'application/json',
      };

        await http
            .post("${GlobalVar.Ip}/wp-json/jwt-auth/v1/token",
                body: body, headers: headers)
            .then((response) {
                var body = json.decode(response.body);
                //var response1;

                if (response.statusCode == 200) {
                    // TODO: you need to store body['token'] to use in some authentication
                    loading = false;
                    Navigator.pushReplacement(context,
                        MaterialPageRoute(builder: (BuildContext ctx) => HomePage()));
    } else {
        // TODO: alert message
        final snackBar = SnackBar(
            content: Text(body['message'].toString().trim()),
        );
        _scaffoldKey.currentState.showSnackBar(snackBar);
    }
    setState(() {
        loading = false;
    });
});
      }

@override
Widget build(BuildContext context) {
    return Scaffold(
        key: _scaffoldKey,
        resizeToAvoidBottomPadding: false,
        body: Container(
            decoration: BoxDecoration(
                image: DecorationImage(
                    image: AssetImage('images/art.png'),
                    fit: BoxFit.fill,
                    colorFilter: ColorFilter.mode(
                        Colors.white12.withOpacity(0.2), BlendMode.dstATop),
                ),
            ),
            child: ListView();
}
导入'dart:convert';
进口“包装:颤振/材料.省道”;
导入“套餐:餐厅应用程序/globalVar.dart”;
导入“套餐:餐厅应用程序/主屏幕.dart”;
导入“套餐:餐厅应用程序/模型/认证镖”;
导入“套餐:餐厅应用程序/注册.dart”;
将“package:http/http.dart”导入为http;
导入“package:restaurant_app/utils/authutils.dart”;
导入“package:shared_preferences/shared_preferences.dart”;
类签名扩展StatefulWidget{
SignIn({Key-Key,this.post}):super(Key:Key);
@凌驾
_SignInState createState()=>\u SignInState();
}
类_SignInState使用SingleTickerProviderStateMixin扩展状态
{
tab控制器;
TextEditingController_email=新建TextEditingController();
TextEditingController_password=新的TextEditingController();
布尔加载;
最终全局密钥\u scaffoldKey=新全局密钥
();
@凌驾
void initState(){
//TODO:实现initState
super.initState();
_fetchSessionAndNavigate();
控制器=新的TabController(长度:2,vsync:this);
加载=假;
}
@凌驾
无效处置(){
//TODO:实现dispose
super.dispose();
controller.dispose();
设置状态(){
加载=假;
});
_email.dispose();
_password.dispose();
}
最终的GlobalKey_formKey=GlobalKey();
bool _autoValidate=false;
_异步登录(用户名、密码){
设置状态(){
加载=真;
});
var body=json.encode({
“用户名”:用户名,
“密码”:密码,
});
映射<字符串,字符串>标题={
“内容类型”:“应用程序/json”,
“接受”:“应用程序/json”,
};
等待http
.post(“${GlobalVar.Ip}/wp json/jwt auth/v1/token”,
正文:正文,标题:标题)
.然后((回应){
var body=json.decode(response.body);
//var响应1;
如果(response.statusCode==200){
//TODO:您需要存储body['token']以用于某些身份验证
加载=假;
Navigator.pushReplacement(上下文,
MaterialPackageRoute(生成器:(BuildContext ctx)=>HomePage());
}否则{
//TODO:警报消息
最终蛇杆=蛇杆(
内容:文本(正文['message'].toString().trim()),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
设置状态(){
加载=假;
});
});
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
钥匙:_scaffoldKey,
resizeToAvoidBottomPadding:false,
主体:容器(
装饰:盒子装饰(
图像:装饰图像(
图像:AssetImage('images/art.png'),
fit:BoxFit.fill,
colorFilter:colorFilter.mode(
颜色。白色12。不透明度(0.2),BlendMode.dStop),
),
),
子:ListView();
}

如果用户详细信息保存在存储器中,您可以导航到
登录
页面,或者使用以下代码导航到
主页
页面

  Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      SharedPreferences prefs = await SharedPreferences.getInstance();
      var email = prefs.getString('email');
      print(email);
      runApp(MaterialApp(home: email == null ? Login() : Home()));
    }
清除注销时的详细信息

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            SharedPreferences prefs = await SharedPreferences.getInstance();
            prefs.remove('email');
            Navigator.pushReplacement(context,
                MaterialPageRoute(builder: (BuildContext ctx) => Login()));
          },
          child: Text('Logout'),
        ),
      ),
    );
  }
}

希望有帮助!

确保
WidgetFlatterBinding.ensureInitialized()
是main()的第一行

import'package:shared_preferences/shared_preferences.dart';
进口“包装:颤振/材料.省道”;
Future main()异步{
WidgetsFlutterBinding.ensureInitialized();
SharedReferences prefs=等待SharedReferences.getInstance();
bool login=prefs.getBool(“登录”);
打印(“login:+login.toString());
runApp(MaterialApp(home:login==null?LoginPage(标题:“我的应用”):HomePage());
}
类LoginPage扩展了无状态小部件{。。。

改为使用用户会话。请查看。该软件包在颤振中添加了用户会话支持,易于使用

// Store value to session
await Consession().set("token", myJWTToken);

// Retrieve item from session
dynamic token = await Consession().get("token");

上述答案使用
SharedReferences
有效(请确保将
WidgetsFlutterBinding.EnsureInitialized();
作为第一行main),但重新启动时它会给你一个空值,也就是说,如果你从最近的应用程序中删除该应用程序并重新打开它,它将不会将你重新定向到主页或配置文件页。我通过向你的应用程序授予写外部存储权限解决了这个问题,因为共享首选项需要在你的设备或模拟器中的某个位置写入数据


只需在您的Android清单文件中添加写入和读取外部存储权限,您就可以使用permission_handler plugin for flatter from pub.dev在运行时从用户处获得所需的权限,当应用程序第一次打开时,共享首选项将不会为您提供
null

特许权现在已被弃用支持。我们现在可以使用flutter_会话无缝管理用户会话

//Write values to the session: 
await FlutterSession().set("token", myJWTToken);

//Read values from the session: 
dynamic token = await FlutterSession().get("token");

这是大量的代码。我建议您(1)将代码减少到最小的相关部分,以及(2)解释您正在尝试做什么以及问题是什么。请参阅谢谢Edman…我已经完成了
// Store value to session
await Consession().set("token", myJWTToken);

// Retrieve item from session
dynamic token = await Consession().get("token");
//Write values to the session: 
await FlutterSession().set("token", myJWTToken);

//Read values from the session: 
dynamic token = await FlutterSession().get("token");