簡體   English   中英

如何在 Flutter 應用程序中的任何位置登錄和訪問后存儲用戶 ID 或“密鑰”?

[英]How to store a User id or "key" after login and access from anywhere in Flutter app?

我正在嘗試確定登錄后存儲和訪問我的 Flutter 應用程序的用戶 object 的最佳方式。 目前還沒有真正的身份驗證。 因此,當“用戶”登錄時,它只需檢查 json 文件中的虛擬用戶名和密碼。 我唯一想知道的是從應用程序的任何位置存儲和訪問我的用戶 ID 的適當方式是什么? 每次屏幕更改時,我都將它作為路由參數傳遞,但這似乎有點矯枉過正。 最合適的方法是什么? 只需創建一個 globals.dart 文件並將用戶 ID 添加為變量?

json 中的用戶示例:

{
    "id" : 5,
    "fName" : "John",
    "lName" : "Doe",
    "position" : "Software Developer",
    "username" : "jdoe",
    "password" : "jdoepass",
    "imageUrl": "assets/images/profile_pictures/profilePicture.png",
    "email" : "jdoe@onepartner.com",
    "location" : "Big Software Company"
}

登錄.dart:

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../utils/opWidgets.dart';
import '../utils/fetchJson.dart';
import '../../entities/User.dart';

/* Description: Login screen widget and functions to handle fetching user json */

class LoginPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginPageState();
  }
}

class _LoginPageState extends State<LoginPage> {
  List<User> _userList = []; //used to represent the list items in the UI
  final userTxtController = TextEditingController();
  final passTxtController = TextEditingController();
  User _currentUser;
  bool _invalidUserMsgVisible = false;

  @override
  initState() {
    //initializes data before build() is called
    //Use this method to initialize data that will be displayed
    //initialize list items using function that fetches/converts json
    fetchUsers().then((value) {
      setState(() {
        _userList.addAll(value);
      });
    });
    super.initState();
  }

  @override
  void dispose() {
    //releases memory
    userTxtController.dispose();
    passTxtController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: GestureDetector(
        //Makes the keyboard collapse when the scaffold body is tapped
        onTap: () => FocusScope.of(context).unfocus(),
        child: _layoutDetails(),
      ),
    );
  }

  //This widget determines the layout of the widgets _logo() and _loginForm() based on the screen's orientation
  Widget _layoutDetails() {
    Orientation orientation = MediaQuery.of(context).orientation;

    if (orientation == Orientation.portrait) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          _logo(),
          _loginForm(),
        ],
      );
    } else {
      return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          _logo(),
          Container(
            width: MediaQuery.of(context).size.width / 1.8,
            height: MediaQuery.of(context).size.height,
            child: _loginForm(),
          ),
        ],
      );
    }
  }

  Widget _logo() {
    return Container(
      width: 225,
      child: Image.asset('assets/images/logos/OPNewLogo.png'),
    );
  }

  Widget _loginForm() {
    return Container(
      width: double.infinity,
      padding: EdgeInsets.all(20),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Visibility(
            visible: _invalidUserMsgVisible,
            child: Text(
              'Username or password is invalid',
              style: GoogleFonts.montserrat(color: Colors.red, fontSize: 14),
            ),
          ),
          SizedBox(height: 5),
          Container(
            //margin: EdgeInsets.symmetric(horizontal: 10),
            width: 500,
            child: opTextField('Username', false, userTxtController),
          ),
          SizedBox(height: 20),
          Container(
            //margin: EdgeInsets.symmetric(horizontal: 10),
            width: 500,
            child: opTextField('Password', true, passTxtController),
          ),
          SizedBox(height: 20),
          Container(
            width: 500,
            height: 40,
            padding: EdgeInsets.symmetric(horizontal: 8),
            child: ElevatedButton(
              onPressed: () => _verifyLogin(
                userTxtController.text.toString().trim(),
                passTxtController.text.toString(),
              ),
              child: Text(
                'LOGIN',
                style: GoogleFonts.montserrat(
                  fontSize: 16,
                  letterSpacing: 1.5,
                  color: Colors.white,
                  fontWeight: FontWeight.w500,
                ),
              ),
              style: ElevatedButton.styleFrom(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20),
                ),
                primary: Theme.of(context).accentColor,
                elevation: 3,
              ),
            ),
          ),
          SizedBox(height: 5),
          Container(
            width: 500,
            height: 40,
            padding: EdgeInsets.symmetric(horizontal: 8),
            child: ElevatedButton(
              onPressed: () => {
                Navigator.pop(context),
              },
              child: Text(
                'REGISTER',
                style: TextStyle(
                    fontSize: 16,
                    letterSpacing: 2.2,
                    color: Theme.of(context).shadowColor,
                    fontWeight: FontWeight.w500),
              ),
              style: ElevatedButton.styleFrom(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20),
                  side: BorderSide(
                    color: Theme.of(context).primaryColorDark,
                  ),
                ),
                primary: Colors.white,
              ),
            ),
          ),
          Container(
            child: TextButton(
              autofocus: false,
              clipBehavior: Clip.none,
              child: Text(
                'Forgot Password',
                style: GoogleFonts.montserrat(
                  fontSize: 15,
                  color: Theme.of(context).shadowColor,
                  decoration: TextDecoration.underline,
                ),
              ),
              onPressed: () =>
                  Navigator.pushNamed(context, resetPasswordPageRoute),
            ),
          ),
        ],
      ),
    );
  }

  //Function to check the username and password input against the list of user objects
  void _verifyLogin(String username, String password) {
    bool _validUser = false;

    //Loop through fetched user objects and check for a match
    for (var user in _userList) {
      if (username == user.username && password == user.password) {
        _validUser = true;
        _currentUser = user; //Set the current user object
        break;
      }
    }
    //If a valid user was found, pop login screen and push home screen
    if (_validUser) {
      Navigator.popAndPushNamed(
        context,
        homePageRoute,
        arguments:
            _currentUser, //Pass the current user object to the home screen
      );
    } else {
      //if no valid user was found, make error message text visible
      setState(() {
        _invalidUserMsgVisible = true;
      });
    }
  }
}

您可以使用 static 和 class 將此數據保存在整個應用程序中

class SaveData{ 
   static int id 
   setId(int id1){
     id = id1;
  }
  getId(){
    return id;
   }
 }

我猜您最終會希望通過超時進行用戶身份驗證,因此需要一種在用戶超時時通知應用程序的方法。 一個很好的方法是使用ChangeNotifierProvider - 有很好的教程,例如Simple app state management 即使在您需要通知之前,使用此機制共享您的 state 也是一個好主意。

這是示例代碼:

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

// User class
class User {
  final String username;
  User(this.username);
  String toString() => username;
}

// AuthService has all authentication logic, notifies listeners
class AuthService with ChangeNotifier {
  User _user;
  User get user => _user;

  Future<void> _authenticate(String email, String password,
      [String name]) async {
    // This is where you authenticate or register the user, and update the state
    _user = User("dummy");
    return Future<void>(() {});
  }

  Future<void> register(String name, String email, String password) async {
    return _authenticate(email, password, name);
  }

  Future<void> login(String email, String password) async {
    return _authenticate(email, password);
  }

  Future<void> logout() async {
    _user = null;
    notifyListeners();
    return Future<void>(() {});
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Put all your ChangeNotifierProviders above MaterialApp
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => AuthService(),
        ),
      ],
      child: MaterialApp(
        title: 'Test App',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: AuthTest(),
      ),
    );
  }
}

class AuthTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
        // Login user
        TextButton(
          child: Text("Login"),
          onPressed: () async {
            await Provider.of<AuthService>(context, listen: false)
                .login("email", "password");
          },
        ),
        // Logout user
        TextButton(
          child: Text("Logout"),
          onPressed: () async {
            await Provider.of<AuthService>(context, listen: false).logout();
          },
        ),
        // Child form
        TextButton(
          child: Text("Form"),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => AuthFormTest()),
            );
          },
        ),
      ]),
    );
  }
}

class AuthFormTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Get AuthService, will rebuild when it notifies listeners
    var authService = Provider.of<AuthService>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('User'),
      ),
      body: Center(child: Text('User: ${authService.user}')),
    );
  }
}

您可以使用shared_preferences庫將您的 id 或 key 保存為 key-value 並在任何地方訪問:

保存:

  SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setInt('id', YOUR_ID);

讀書:

prefs.getInt('id');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM