点击上方蓝字关注我,知识会给你力量
在编写 Flutter 应用程序时,将业务逻辑与 UI 代码分离是非常重要的。
这将使我们的代码更易于测试和推理,当我们的应用程序变得越来越复杂时,这一点尤为重要。
为了实现这一点,我们可以使用设计模式在应用程序的不同组件之间引入关注点分离。
作为参考,我们可以采用分层应用程序架构,如图所示:
这一次,我们将重点关注表现层,学习如何使用Controller来:
保存业务逻辑
管理Widget状态
与数据层中的Repository交互
❝这种Controller与 MVVM 模式中使用的视图模型相同。如果您以前使用过 flutter_bloc,那么它的作用与 cubit 相同。
我们将学习 AsyncNotifier 类,它是 Flutter SDK 中 StateNotifier 和 ValueNotifier / ChangeNotifier 类的替代。
为了让它更有用,我们将以实现一个简单的身份验证流程为例。
准备好了吗?开始吧
简单的身份验证流程
让我们考虑一个非常简单的应用程序,我们可以用它来匿名登录并在两个屏幕之间切换:
在本文中,我们将重点讨论如何实现以下功能:
一个可用于登录和注销的授权存储库
一个向用户显示的登录 widget 界面
一个在两者之间起中介作用的相应Controller类
以下是此特定示例的简化版参考架构:
AuthRepository 类
作为起点,我们可以定义一个简单的抽象类,它包含三个方法,我们将用它们来登录、注销和检查身份验证状态:
abstract class AuthRepository {
// emits a new value every time the authentication state changes
Stream<AppUser?> authStateChanges();
Future<AppUser> signInAnonymously();
Future<void> signOut();
}
实际上,我们还需要一个实现 AuthRepository 的具体类。该类可以基于 Firebase 或任何其他后端。我们现在甚至可以用一个假的Repository来实现它。为完整起见,我们还可以定义一个简单的 AppUser 模型类:
/// Simple class representing the user UID and email.
class AppUser {
const AppUser({required this.uid});
final String uid;
// TODO: Add other fields as needed (email, displayName etc.)
}
如果我们使用 Riverpod,我们还需要一个provider来访问我们的Repository:
final authRepositoryProvider = Provider<AuthRepository>((ref) {
// return a concrete implementation of AuthRepository
return FakeAuthRepository();
});
接下来,让我们来关注一下登录界面。
SignInScreen Widget
假设我们有一个简单的 SignInScreen Widget,定义如下:
import 'package:flutter_riverpod/flutter_riverpod.dart';
class SignInScreen extends ConsumerWidget {
const SignInScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref)&nbs