在Flutter项目中,即使不使用Provider,也可以通过其他方法实现MVVM架构中的页面数据管理和前后端分离。下面以一个简单的登录页面作为示例,其中ViewModel负责处理业务逻辑,而View负责展示UI及与用户的交互。
创建一个用户Model,首先,定义一个User模型
class User {
String username; // 用户登录账号
String password; // 登录密码
User({required this.username, required this.password});
}
接着创建一个名为 LoginViewModel 的 ViewModel,它将包含登录的业务逻辑,比如验证用户名和密码。
class LoginViewModel {
String? _username; // 用户登录账户
String? _password; // 用户登录密码
bool _isFormValid = false; // 请求接口前判断登录账户和登录密码不能为空
String? get username => _username;
String? get password => _password;
bool get isFormValid => _isFormValid;
void updateUsername(String value) {
_username = value;
_updateFormValidity();
}
void updatePassword(String value) {
_password = value;
_updateFormValidity();
}
void _updateFormValidity() {
_isFormValid = _username != null && _username!.isNotEmpty && _password != null && _password!.isNotEmpty;
}
Future<void> submitLogin() async {
// 这里可以添加网络请求逻辑,模拟则直接打印
if (_isFormValid) {
print('Logging in with username: $_username and password: $_password');
} else {
print('Form is not valid!');
}
}
}
最后,创建登录页面 (UI层)LoginPage,在这个页面中,我们直接使用ViewModel来控制UI的显示和响应用户的输入。
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
late LoginViewModel _loginViewModel = LoginViewModel();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('登录页')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _usernameController,
onChanged: (value) => _loginViewModel.updateUsername(value),
decoration: InputDecoration(labelText: 'Username'),
),
SizedBox(height: 16),
TextField(
controller: _passwordController,
obscureText: true,
onChanged: (value) => _loginViewModel.updatePassword(value),
decoration: InputDecoration(labelText: 'Password'),
),
SizedBox(height: 24),
ElevatedButton(
onPressed: _loginViewModel.isFormValid ? () async {
_loginViewModel.submitLogin();
} : null,
child: Text('Login'),
),
],
),
),
);
}
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
}
在这个登录例子中,ViewModel直接在页面(_LoginPageState)中创建和管理,没有使用Provider。用户输入通过 TextField 和 onChanged 回调传递给ViewModel进行处理,而登录按钮的可用性则直接根据ViewModel的 isFormValid,属性来决定。当点击登录按钮时,调用ViewModel中的 submitLogin 方法执行登录操作。
虽然这个方法直接在页面内部管理状态,随着应用复杂度增加,手动管理ViewModel的生命周期和状态共享可能会变得困难,这时引入Provider或其它状态管理库就会显得更加合适。