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

时间:2019-01-26 09:33:18

标签: flutter woocommerce-rest-api

我希望在用户成功登录后继续保持用户登录状态。 我正在使用REST API来检索用户的用户名和密码。但是我想保存这些详细信息,以便用户可以保持登录状态。我目前的情况是我可以成功登录用户,但是当我重新启动应用程序时,我必须再次登录,因此我需要将用户的详细信息保存在共享首选项,以便用户可以在整个会话之前保持登录状态,直到注销为止。但是我无法执行此操作,因此请帮助我。 预先感谢

这是我登录页面的代码。 我删除了应该在列表视图中的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();
}

5 个答案:

答案 0 :(得分:2)

如果用户详细信息已保存在存储中,则可以导航至Login页面,否则,使用以下代码即可导航至Home页面

Future<void> main() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  var email = prefs.getString('email');
  print(email);
  runApp(MaterialApp(home: email == null ? Login() : Home()));
}

成功登录后保存所需的用户详细信息

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            //after the login REST api call && response code ==200
            SharedPreferences prefs = await SharedPreferences.getInstance();
            prefs.setString('email', 'useremail@gmail.com');
            Navigator.pushReplacement(context,
                MaterialPageRoute(builder: (BuildContext ctx) => Home()));
          },
          child: Text('Login'),
        ),
      ),
    );
  }
}

清除注销详细信息

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'),
        ),
      ),
    );
  }
}

希望有帮助!

答案 1 :(得分:2)

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

import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences prefs = await SharedPreferences.getInstance();
  bool login = prefs.getBool("login");
  print("login:" + login.toString());
  runApp(MaterialApp(home: login == null ? LoginPage(title: 'My App') : HomePage()));
}

class LoginPage extends StatelessWidget { ...

答案 2 :(得分:2)

使用SharedPreferences的上述答案有效(确保您将WidgetsFlutterBinding.ensureInitiazed();作为主行的第一行),但是在重新启动时(即,如果您删除了该应用程序)它将为您提供空值从最近开始并重新打开它,它不会将您重定向到“主页”或“个人资料”页面。我通过向您的应用程序授予写入外部存储权限来解决此问题,因为共享首选项需要将数据写入设备或仿真器中的某个位置。

只需在Android Manifest文件中添加写入和读取外部存储权限,就可以使用Permission.handler插件从pub.dev中轻松获取内容,以便在首次打开该应用程序时在运行时从用户那里获取所需的权限,然后进行共享偏好设置不会给您null

答案 3 :(得分:0)

改为使用用户会话。签出Consession。该软件包在Flutter中增加了对用户会话的支持,并且易于使用。

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

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

答案 4 :(得分:0)

现在不赞成使用优惠,而推荐使用flutter_session。现在,我们可以使用flutter_session无缝管理用户会话。

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

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