flutter: 用riverpod分离view层和viewmodel层
一,安装
项目地址:
https://pub.dev/packages/flutter_riverpod
安装:
dependencies:
flutter:
sdk: flutter
go_router: ^17.2.3
flutter_riverpod: ^3.2.1
二,代码:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myrouter/router/router.dart';
void main() {
// 包裹ProviderScope,使整个APP可以使用Riverpod
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
routerConfig: router,
);
}
router.dart
import 'package:myrouter/pages/home_page.dart';
import 'package:go_router/go_router.dart';
import 'package:myrouter/views/UserView.dart';
final router = GoRouter(routes: [
GoRoute(
path: "/",
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/setting',
builder: (context, state) {
// ✨ 核心代码:从 state.uri.queryParameters 中提取参数
final id = state.uri.queryParameters['id'] ?? 0;
final name = state.uri.queryParameters['name'] ?? '';
final idint = int.tryParse(id?.toString() ?? '') ?? 0;
return UserView(
id: idint,
name: name,
);
},
)
]);
UserModel.dart
class UserModel {
final int id;
final String name;
UserModel({required this.id, required this.name});
}
home_page.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
String name = '苏轼';
int id = 123;
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('主页'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'主页',
style: TextStyle(fontSize: 40),
),
// 点击跳转到设置页面
ElevatedButton(
onPressed: () => GoRouter.of(context).push('/setting?name=${name}&id=${id}'),
style: ElevatedButton.styleFrom(
foregroundColor: Theme.of(context).colorScheme.onSecondary,
backgroundColor: Theme.of(context).colorScheme.secondary,
),
child: const Text('跳转到设置页面'),
)
],
),
),
);
}
}
UserViewModel.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/userModel.dart';
// ViewModel: 负责业务逻辑
class UserViewModel extends Notifier<UserModel?> {
@override
UserModel? build() => null; // 初始状态为空
// 更新用户信息
void setUser(int id, String name) {
state = UserModel(id: id, name: name);
}
// 模拟修改用户信息的方法
void updateUserInfo(int newId, String newName) {
state = UserModel(id: newId, name: newName);
}
}
// 全局 Provider:让 View 可以访问这个 ViewModel
final userProvider = NotifierProvider<UserViewModel, UserModel?>(() {
return UserViewModel();
});
UserView.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../viewmodels/UserViewModel.dart';
class UserView extends ConsumerStatefulWidget {
final int id;
final String name;
const UserView({super.key, required this.id, required this.name});
@override
ConsumerState<UserView> createState() => _DetailPageState();
}
class _DetailPageState extends ConsumerState<UserView> {
@override
void initState() {
super.initState();
// 💡 关键点:进入页面时,将路由参数存入 ViewModel
Future.microtask(() {
ref.read(userProvider.notifier).setUser(widget.id, widget.name);
});
}
@override
Widget build(BuildContext context) {
// 监听 ViewModel 中的数据变化
final user = ref.watch(userProvider);
return Scaffold(
appBar: AppBar(title: const Text('详情页')),
body: Center(
child: user == null
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('ID: ${user.id}', style: const TextStyle(fontSize: 24)),
Text('姓名: ${user.name}', style: const TextStyle(fontSize: 24)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// ✨ 核心:调用 ViewModel 的方法修改数据
ref.read(userProvider.notifier).updateUserInfo(101, "杨万里");
},
child: const Text('更新为杨万里'),
),
],
),
),
);
}
}
三,测试效果:


浙公网安备 33010602011771号