Flutter用户管理插件easyuser的使用
Flutter用户管理插件easyuser的使用
Easy User
是一个基于 Firebase Realtime Database 的用户管理包。本文将详细介绍如何使用该插件进行用户管理。
安全规则
安装数据库安全规则文件:
安装来自 <a href="https://github.com/thruthesky/easy_packages/blob/main/docs/database_security_rules.json" rel="ugc">database security rules</a> 文件的安全规则。
数据库结构
数据库结构如下:
users
: 是数据库的根节点。users/<uid>
: 是用户的节点。users/<uid>/name
: 用户的名字。users/<uid>/photoUrl
: 用户的照片URL。users/<uid>/role
: 用户的角色。users/<uid>/status
: 用户的状态。users/<uid>/createdAt
: 用户的创建日期。users/<uid>/updatedAt
: 用户的最后更新日期。users/<uid>/deletedAt
: 用户的删除日期。users/<uid>/deleted
: 用户的删除状态。users/<uid>/password
: 用户的密码。users/<uid>/phone
: 用户的电话号码。users/<uid>/address
: 用户的地址。users/<uid>/gender
: 用户的性别。可以是"M"或"F"。users/<uid>/birthYear
: 用户的出生年份。users/<uid>/birthMonth
: 用户的出生月份。users/<uid>/birthDay
: 用户的出生日期。
user-phone-sign-in-numbers
: 是存储用户用于登录的电话号码的列表。user-phone-sign-in-numbers/<phoneNumber>
: 用户用于登录的电话号码。user-phone-sign-in-numbers/<phoneNumber>/lastSignedInAt
: 用户使用电话号码登录的时间(毫秒)。
小部件
UserField
UserField
小部件仅获取并显示用户数据的一个字段。
UserField<int?>(
uid: user.uid, // 用户ID
field: 'birthDay', // 字段名
builder: (v) { // 构建函数
return ElevatedButton(
onPressed: () async {
final easyUser = await User.get(user.uid);
easyUser?.ref.child(User.field.birthDay).set((v ?? 0) + 1);
},
child: Text('UserField(birthDay): $v'),
);
},
)
UserModel
UserModel
小部件通过构建方法传递用户模型对象。这意味着此小部件可以显示所有用户数据。
UserModel(
uid: user.uid, // 用户ID
builder: (userData) { // 构建函数
return Text('User ID: ${userData.uid}');
},
)
UserAvtar
UserAvtar
小部件用于显示用户头像。
UserBuildAvatar(
photoUrl: null, // 用户照片URL
initials: null // 用户初始字母
)
UI 和 UX 自定义
自定义公共个人资料屏幕前缀操作构建器:
自定义公共个人资料屏幕前缀操作构建器。
逻辑
账号关联
/registered-phone-number
: 检查电话号码是否已注册的节点。- 为什么?
- 为了将电话号码与现有用户账户关联。
- 用户可能使用其他登录方式(如匿名、邮箱、Google、Apple、Facebook等)。
- 如果电话号码已经注册(或之前登录过),意味着该电话号码属于一个账户。
- 不能将电话号码与另一个账户关联。
- 一旦电话号码凭证被使用,就不能再次使用(凭证可能在其他方式下重复使用)。
- 可以尝试将电话号码凭证关联,并且如果成功,则已关联。
- 但如果失败,不能重新使用凭证。这意味着用户必须通过其他方式获得新凭证。
- 为什么?
flowchart TB
node_1(["Anonymous User Login"])
node_2{"Phone Sign-In with Anonymous Account Link?"}
node_3["Provide if the phone number is registered already"]
node_1 --> node_2
node_2 --"Yes"--> node_3
电话号码登录
- 如果用户使用电话号码登录,则电话号码会保存在
user-phone-sign-in-numbers/<phoneNumber>
节点。- 这仅用于检查电话号码是否已注册。
- 如果电话号码未注册,则用户可以将账户与电话号码关联。
- 如果电话号码已注册,则用户不能将电话号码与账户关联。相反,用户可以使用电话号码登录。
- 如果系统需要重置用户的电话号码,则在
easy-engine/tools
目录下运行tsx reset-phone-sign-in-numbers
命令。
示例代码
以下是一个完整的示例代码,展示了如何使用 easyuser
插件进行用户管理。
import 'dart:developer';
import 'dart:math' hide log;
import 'package:easy_locale/easy_locale.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_auth/firebase_auth.dart' hide User;
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:easyuser/easyuser.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
lo.init();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String firebaseAppName = '[DEFAULT]';
[@override](/user/override)
void initState() {
super.initState();
UserService.instance.init();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AuthStateChanges(
builder: (user) {
return user == null
? const EmailPasswordLogin()
: Column(
children: [
Text('User UID: ${user.uid}'),
ElevatedButton(
onPressed: () => UserService.instance.showProfileUpdateScreen(context),
child: const Text('Profile update'),
),
ElevatedButton(
onPressed: () => i.signOut(),
child: const Text('Sign out'),
),
UserField<int?>(
uid: user.uid,
field: 'birthDay',
builder: (v) {
return ElevatedButton(
onPressed: () async {
final easyUser = await User.get(user.uid);
easyUser?.ref.child(User.field.birthDay).set((v ?? 0) + 1);
},
child: Text('UserField(birthDay): $v'),
);
},
),
const UserUpdateAvatar(),
ElevatedButton(
onPressed: () async {
await UserService.instance.showBlockListScreen(context);
},
child: const Text("Show Block list"),
),
],
);
},
),
ElevatedButton(
onPressed: () async {
final user = await UserService.instance.showSearchDialog(
context,
exactSearch: true,
);
if (user == null) return;
if (!context.mounted) return;
UserService.instance.showPublicProfileScreen(context, user: user);
},
child: const Text('User Search Dialog'),
),
const Divider(),
ElevatedButton(
onPressed: () async {
await UserService.instance.showProfileUpdateScreen(context);
},
child: const Text("Update Profile"),
),
const Divider(),
const Text('TESTS'),
ElevatedButton(
onPressed: () async {
log("Begin Test", name: '❗️');
final errors = await UserTestService.instance.test([
getDataTest,
recordPhoneSignInNumberTest,
alreadyRegisteredPhoneNumberTest,
anonymousSignInTest,
displayNameUpdateTest,
nameUpdateTest,
yearUpdate,
birthMonthUpdate,
birthDayUpdate,
genderUpdate,
photoUrlUpdate,
stateMessageUpdate,
statePhotoUrlUpdate,
userDeletetest,
userResigntest,
]);
debugPrint(
"Errors: ${errors.length}",
);
for (String e in errors) {
log(
"Error: $e",
name: '❌',
);
}
},
child: const Text('TEST ALL')),
const Divider(),
ElevatedButton(
onPressed: () async {
final refTest = FirebaseDatabase.instance.ref().child("test").child(myUid!);
await refTest.set({
"field1": "val1",
"field2": "val2",
"field3": "val3",
});
debugPrint("==============");
debugPrint("==============");
debugPrint("Getting using Get: ");
final getValue = await refTest.child("field1").get();
debugPrint("Get Value: ${getValue.value}");
debugPrint("Getting using Once: ");
final onceValue = await refTest.child("field1").once();
debugPrint("Once Value: ${onceValue.snapshot.value}");
debugPrint("==============");
debugPrint("Getting null using Get: ");
final getNullValue = await refTest.child("nullField").get();
debugPrint("Get Null Value: ${getNullValue.value}");
debugPrint("Getting null using Once: ");
final onceNullValue = await refTest.child("nullField").once();
debugPrint("Once Null Value: ${onceNullValue.snapshot.value}");
},
child: const Text("Firebase Get vs Once"),
),
const Divider(),
ElevatedButton(
onPressed: recordPhoneSignInNumberTest,
child: const Text("Record Phone Number Test"),
),
ElevatedButton(
onPressed: alreadyRegisteredPhoneNumberTest,
child: const Text("Already Registered Phone Number Test"),
),
const Divider(),
ElevatedButton(
onPressed: () async {
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
},
child: const Text('Create a user'),
),
ElevatedButton(
onPressed: deleteFieldTest,
child: const Text('Delete Field Test'),
),
ElevatedButton(
onPressed: anonymousSignInTest,
child: const Text('Anonymous sign in test'),
),
ElevatedButton(
onPressed: blockUserTest,
child: const Text('Block user test'),
),
ElevatedButton(
onPressed: getDataTest,
child: const Text('Get data'),
),
ElevatedButton(
onPressed: getFieldTest,
child: const Text('Get field'),
),
ElevatedButton(
onPressed: displayNameUpdateTest,
child: const Text('Update display name'),
),
ElevatedButton(
onPressed: displayNameUpdateTest,
child: const Text('Update name'),
),
ElevatedButton(
onPressed: yearUpdate,
child: const Text('Update birthYear'),
),
ElevatedButton(
onPressed: birthMonthUpdate,
child: const Text('Update birthMonth'),
),
ElevatedButton(
onPressed: birthDayUpdate,
child: const Text('Update birthDay'),
),
ElevatedButton(
onPressed: genderUpdate,
child: const Text('Update gender'),
),
ElevatedButton(
onPressed: photoUrlUpdate,
child: const Text('Update photoUrl'),
),
ElevatedButton(
onPressed: stateMessageUpdate,
child: const Text('Update stateMessage'),
),
ElevatedButton(
onPressed: statePhotoUrlUpdate,
child: const Text('Update statePhotoUrl'),
),
ElevatedButton(
onPressed: statePhotoUrlUpdate,
child: const Text('Update statePhotoUrl'),
),
ElevatedButton(
onPressed: userDeletetest,
child: const Text("Delete user"),
),
ElevatedButton(
onPressed: userResigntest,
child: const Text("Resign user"),
),
const SafeArea(
child: SizedBox(
height: 50,
),
),
],
),
),
);
}
static const phoneNumber = "+11111111111";
PhoneAuthCredential? _phoneAuthCredential;
_logInAs11111111111() async {
const verificationCode = "111111";
// Step 1: Sign out any previous session
await UserService.instance.signOut();
// Step 2: Start phone number verification
await FirebaseAuth.instance.verifyPhoneNumber(
autoRetrievedSmsCodeForTesting: verificationCode,
phoneNumber: phoneNumber,
verificationCompleted: (PhoneAuthCredential credential) async {
await FirebaseAuth.instance.signInWithCredential(credential);
debugPrint('Auto-sign in completed');
},
verificationFailed: (FirebaseAuthException error) {
debugPrint('Verification failed: ${error.message}');
},
codeSent: (String verificationId, int? resendToken) async {
debugPrint('Code sent. Please enter the verification code.');
// Wait for the code to be sent and verificationId to be set
// Step 3: Manually sign in using the verification code and verificationId
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: verificationCode,
);
// Sign in with the credential
await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
debugPrint('Phone number successfully verified and signed in.');
_phoneAuthCredential = phoneAuthCredential;
},
codeAutoRetrievalTimeout: (String verificationId) async {
debugPrint('Auto retrieval timeout. Manual sign-in required.');
// Wait for the code to be sent and verificationId to be set
// Step 3: Manually sign in using the verification code and verificationId
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: verificationCode,
);
// Sign in with the credential
await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
_phoneAuthCredential = phoneAuthCredential;
},
timeout: const Duration(seconds: 120), // Set the timeout duration
);
}
bool checkTimeWithin30Seconds(int timestamp, int timestamp2) {
final difference = (timestamp - timestamp2).abs();
// 30 seconds = 30 * 1000 milliseconds
if (difference <= 30 * 1000) {
debugPrint("The timestamp is within 30 seconds of the current time.");
return true;
} else {
debugPrint("The timestamp is not within 30 seconds of the current time.");
return false;
}
}
recordPhoneSignInNumberTest() async {
await UserService.instance.signOut();
// To clear the user-phone-sign-in-numbers node
await UserService.instance.database.ref('user-phone-sign-in-numbers').set(null);
await _logInAs11111111111();
await waitUntil(() async => UserService.instance.user != null);
final timeNow = DateTime.now().millisecondsSinceEpoch;
debugPrint("Is it recorded? ${await UserService.instance.isPhoneNumberRegistered(phoneNumber)}");
final checkRecord = await UserService.instance.database
.ref()
.child('user-phone-sign-in-numbers')
.child(phoneNumber)
.child("lastSignedInAt")
.get();
debugPrint("Last Signed in at: ${checkRecord.value}");
assert(checkRecord.value != null, "recordPhoneSignInNumberTest: The phone sign in was not recorded.");
final lastSignedInAt = checkRecord.value as int;
debugPrint("lastSignedInAt $lastSignedInAt");
assert(
checkTimeWithin30Seconds(lastSignedInAt, timeNow),
"recordPhoneSignInNumberTest: It's either delayed, or not recorded with correct time. Difference: ${(lastSignedInAt - timeNow).abs()}",
);
}
alreadyRegisteredPhoneNumberTest() async {
// There is no linkingAuthToAnonymous in User Service dart.
Object? error;
try {
// SignOut
await UserService.instance.signOut();
// Login anonymously
await UserService.instance.initAnonymousSignIn();
// Login as 111 and link
await _logInAs11111111111();
await waitUntil(() async => UserService.instance.user != null);
await FirebaseAuth.instance.currentUser?.linkWithCredential(_phoneAuthCredential!);
// Sign Out
await UserService.instance.signOut();
// Login anonymously
await UserService.instance.initAnonymousSignIn();
// Login as 111 and link
await _logInAs11111111111();
// Login as 111 and link
await waitUntil(() async => UserService.instance.user != null);
await FirebaseAuth.instance.currentUser?.linkWithCredential(_phoneAuthCredential!);
} catch (e) {
error = e;
}
assert(error == null, "alreadyRegisteredPhoneNumberTest: There is an error: $error");
if (error == null) {
log("No error", name: '🟢');
} else {
log("ERROR", name: '🔴');
debugPrint(error.toString());
}
}
deleteFieldTest() async {
await UserService.instance.signOut();
final uid1 = await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await Future.delayed(const Duration(milliseconds: 500));
const testDisplayNameVal = "Test Display Name";
const testNameVal = "Test Name";
await my.update(
displayName: testDisplayNameVal,
name: testNameVal,
);
final myDataUpdate = await User.get(uid1, cache: false);
assert(
myDataUpdate?.displayName == testDisplayNameVal,
"deleteFieldTest: Something went wrong in the middle of testing",
);
assert(
myDataUpdate?.name == testNameVal,
"deleteFieldTest: Something went wrong in the middle of testing",
);
await my.deleteFields([User.field.displayName]);
await Future.delayed(const Duration(milliseconds: 500));
final displayNameUpdate = await User.getField(uid: uid1, field: User.field.displayName, cache: false);
debugPrint("displayNameUpdate: $displayNameUpdate");
final nameUpdate = await User.getField(uid: uid1, field: User.field.name, cache: false);
assert(
displayNameUpdate == null,
"deleteFieldTest: Display name SHOULD be deleted",
);
assert(
nameUpdate == testNameVal,
"deleteFieldTest: Name field should NOT be deleted",
);
}
anonymousSignInTest() async {
await UserService.instance.signOut();
final originalSetup = UserService.instance.enableAnonymousSignIn;
UserService.instance.enableAnonymousSignIn = true;
await UserService.instance.initAnonymousSignIn();
await waitUntil(() async => UserService.instance.user != null);
UserService.instance.enableAnonymousSignIn = originalSetup;
assert(
i.anonymous,
"anonymousSignInTest: Unable to login as anonymous",
);
}
blockUserTest() async {
UnimplementedError("Unable to Unit test because of confirmation");
// User 1
await UserService.instance.signOut();
final uid1 = await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
// User 2
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
if (!context.mounted || !mounted) return;
// Block user 1
await UserService.instance.block(context: context, otherUid: uid1);
assert(
UserService.instance.blocks.containsKey(uid1),
"blockUserTest: Unable to block user 1, uid: $uid1, myUid: ${my.uid}",
);
}
getDataTest() async {
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
final getMy = await User.get(my.uid, cache: false);
assert(
getMy != null,
"getDataTest: User.get failed to get my User",
);
}
getFieldTest() async {
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await Future.delayed(const Duration(milliseconds: 500));
await UserService.instance.usersRef.child(myUid!).child("testField").set("testing");
final testField = await User.getField(uid: myUid!, field: "testField");
debugPrint("testField: $testField");
final testfield2Once =
await FirebaseDatabase.instance.ref("users").child(myUid!).child("testField").once();
debugPrint("testField2: ${testfield2Once.snapshot.value}");
final testfield2Get =
await FirebaseDatabase.instance.ref("users").child(myUid!).child("testField").get();
debugPrint("testField2: ${testfield2Get.value}");
}
displayNameUpdateTest() async {
final displayName = 'newDisplayName:${DateTime.now().millisecond}';
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
displayName: displayName,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.displayName == displayName,
"uid: ${my.uid}, updated displayName from Database: ${updated.displayName} vs displayName: $displayName",
);
}
nameUpdateTest() async {
final name = 'newName:${DateTime.now().millisecond}';
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
name: name,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.name == name,
"nameUpdateTest: uid: ${my.uid}, updated name from Database: ${updated.name} vs name: $name",
);
}
yearUpdate() async {
final newBirthYear = DateTime.now().millisecond;
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
birthYear: newBirthYear,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.birthYear == newBirthYear,
"yearUpdate: uid: ${my.uid}, updated birthYear from Database: ${updated.birthYear} vs newBirthYear: $newBirthYear",
);
}
birthMonthUpdate() async {
final newBirthMonth = DateTime.now().millisecond;
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
birthMonth: newBirthMonth,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.birthMonth == newBirthMonth,
"birthMonthUpdate: uid: ${my.uid}, updated birthMonth from Database: ${updated.birthMonth} vs newBirthMonth: $newBirthMonth",
);
}
birthDayUpdate() async {
final newBirthDay = DateTime.now().millisecond;
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
birthDay: newBirthDay,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.birthDay == newBirthDay,
"birthDayUpdate: uid: ${my.uid}, updated birthDay from Database: ${updated.birthDay} vs newBirthDay: $newBirthDay",
);
}
genderUpdate() async {
final newGender = ['M', 'F'][Random().nextInt(2)];
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
gender: newGender,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.gender == newGender,
"genderUpdate: uid: ${my.uid}, updated gender from Database: ${updated.gender} vs newGender: $newGender",
);
}
photoUrlUpdate() async {
final photoUrl = 'photoUrl:${DateTime.now().millisecond}';
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
photoUrl: photoUrl,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.photoUrl == photoUrl,
"photoUrlUpdate: uid: ${my.uid}, updated photoUrl from Database: ${updated.photoUrl} vs newGender: $photoUrl",
);
}
stateMessageUpdate() async {
final stateMessage = 'stateMessage:${DateTime.now().millisecond}';
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
stateMessage: stateMessage,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.stateMessage == stateMessage,
"stateMessageUpdate: uid: ${my.uid}, updated stateMessage from Database: ${updated.stateMessage} vs stateMessage: $stateMessage",
);
}
statePhotoUrlUpdate() async {
final statePhotoUrl = 'statePhotoUrl:${DateTime.now().millisecond}';
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
statePhotoUrl: statePhotoUrl,
);
final updated = await User.get(my.uid, cache: false);
assert(
updated!.statePhotoUrl == statePhotoUrl,
"statePhotoUrlUpdate: uid: ${my.uid}, updated statePhotoUrl from Database: ${updated.statePhotoUrl} vs statePhotoUrl: $statePhotoUrl",
);
}
userDeletetest() async {
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
final myUid = my.uid;
await UserService.instance.user!.update(
name: "test name",
);
final checkUpdate = await User.get(myUid, cache: false);
debugPrint("Check if Updated: ${checkUpdate?.name ?? 'null'}");
await UserService.instance.user!.delete();
final deleted = await User.get(myUid, cache: false);
debugPrint("Check if nulled: ${deleted?.name ?? 'null'}");
assert(
deleted == null,
"userDeletetest: uid: $myUid, deleted from Database: $deleted",
);
}
userResigntest() async {
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
await UserService.instance.user!.update(
name: "test name",
);
final oldUid = my.uid;
final checkUpdate = await User.get(oldUid, cache: false);
debugPrint("Check if Updated: ${checkUpdate?.name ?? 'null'}");
debugPrint("Resigning user: ${i.auth.currentUser?.uid}");
await UserService.instance.resign();
// Check if deleted
await UserService.instance.signOut();
await UserTestService.instance.createTestUser();
await waitUntil(() async => UserService.instance.user != null);
final deleted = await User.get(oldUid, cache: false);
assert(
deleted == null,
"userResignTest: uid: $oldUid, deleted from Database: $deleted",
);
}
}
更多关于Flutter用户管理插件easyuser的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter用户管理插件easyuser的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,作为一个IT专家,我可以为你提供一个关于如何在Flutter项目中使用easy_user
插件进行用户管理的代码示例。easy_user
是一个假设的插件名称,因为实际上并没有一个广泛知名的名为easy_user
的官方Flutter插件。不过,我会根据常见的用户管理功能(如注册、登录、用户信息存储等)给出一个示例代码,你可以根据实际需要和插件的API进行调整。
假设我们有一个名为easy_user
的插件,它提供了以下功能:
- 用户注册(
register
) - 用户登录(
login
) - 获取当前用户信息(
getCurrentUser
) - 登出(
logout
)
以下是一个示例代码,展示了如何使用这个假设的easy_user
插件:
import 'package:flutter/material.dart';
import 'package:easy_user/easy_user.dart'; // 假设的插件导入
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Easy User Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: UserManagementScreen(),
);
}
}
class UserManagementScreen extends StatefulWidget {
@override
_UserManagementScreenState createState() => _UserManagementScreenState();
}
class _UserManagementScreenState extends State<UserManagementScreen> {
final EasyUser _easyUser = EasyUser(); // 初始化插件实例
String _userStatus = 'Not Logged In';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('User Management'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'User Status: $_userStatus',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
await _registerUser();
},
child: Text('Register'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () async {
await _loginUser();
},
child: Text('Login'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () async {
await _logoutUser();
},
child: Text('Logout'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () async {
await _getCurrentUser();
},
child: Text('Get Current User'),
),
],
),
),
);
}
Future<void> _registerUser() async {
try {
// 假设注册需要email和password
String email = 'test@example.com';
String password = 'password123';
await _easyUser.register(email: email, password: password);
setState(() {
_userStatus = 'Registered Successfully';
});
} catch (e) {
print('Registration Error: $e');
setState(() {
_userStatus = 'Registration Failed';
});
}
}
Future<void> _loginUser() async {
try {
String email = 'test@example.com';
String password = 'password123';
await _easyUser.login(email: email, password: password);
User? user = await _easyUser.getCurrentUser();
setState(() {
_userStatus = 'Logged In as ${user?.email ?? 'Unknown'}';
});
} catch (e) {
print('Login Error: $e');
setState(() {
_userStatus = 'Login Failed';
});
}
}
Future<void> _logoutUser() async {
try {
await _easyUser.logout();
setState(() {
_userStatus = 'Not Logged In';
});
} catch (e) {
print('Logout Error: $e');
setState(() {
_userStatus = 'Logout Failed';
});
}
}
Future<void> _getCurrentUser() async {
try {
User? user = await _easyUser.getCurrentUser();
setState(() {
_userStatus = 'Current User: ${user?.email ?? 'Not Logged In'}';
});
} catch (e) {
print('Get Current User Error: $e');
setState(() {
_userStatus = 'Failed to Get Current User';
});
}
}
}
// 假设的用户模型
class User {
String? email;
String? name;
// 其他用户属性...
User({this.email, this.name});
@override
String toString() {
return 'User{email: $email, name: $name}';
}
}
请注意,上述代码是基于假设的easy_user
插件API编写的。在实际使用中,你需要根据具体插件的文档来调整代码。例如,实际的插件可能会有不同的方法名称、参数或返回类型。务必参考插件的官方文档来获取正确的API信息。
此外,如果你正在寻找一个实际的Flutter用户管理插件,可以考虑使用如firebase_auth
这样的插件,它提供了强大的用户认证功能,并且与Flutter生态系统紧密集成。