如何存储用户ID或“密钥"?登录并从Flutter应用程序中的任何位置访问后? [英] How to store a User id or "key" after login and access from anywhere in Flutter app?
问题描述
我正在尝试确定登录后存储和访问Flutter应用程序的User对象的最佳方法.到目前为止,还没有真正的身份验证.因此,当用户"登录它只是检查json文件中的虚拟用户名和密码.我唯一想知道的是从应用程序中的任何位置存储和访问我的用户ID的适当方法是什么?每次屏幕更改时,我都一直将其作为路由参数传递,但这似乎有点过头了.最合适的方法是什么?只需创建一个globals.dart文件并将用户ID添加为变量?
I am trying to determine the best way to store and access my Flutter app's User object after a login. There is no real authentication as of right now. So when the "user" logs in it just checks a json file for a dummy username and password. The only thing I want to know is what is the appropriate way to store and access my User id from anywhere in the app? I have been passing it as a route parameter every time the screen changes but that seems like overkill. What is the most appropriate way to do this? Just create a globals.dart file and add the user id as a variable?
json中的用户示例:
Example of User in 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"
}
Login.dart:
Login.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;
});
}
}
}
推荐答案
我想您最终将希望通过超时进行用户身份验证,因此需要一种方法来在用户超时时通知应用程序.一个很好的方法是使用 ChangeNotifierProvider
-有很好的教程,例如简单的应用程序状态管理.使用此机制来共享您的状态是一个好主意,甚至在您需要通知之前.
I guess you will eventually want to have user authentication with timeout, so will need a way to notify the app when the user times out. A good way to do this is using ChangeNotifierProvider
- there are good tutorials, e.g. Simple app state management. It is a good idea to use this mechanism to share your state, even before you need notifications.
这是示例代码:
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}')),
);
}
}
这篇关于如何存储用户ID或“密钥"?登录并从Flutter应用程序中的任何位置访问后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!