如何使用Bloc Pattern根据用户ID分配对应的待办事项?
现有问题修正
- 你当前编写的
findByID逻辑无效:element.id == element.id判断条件永远为真,筛选结果和原列表完全一致,没有筛选作用。 - 该方法不需要设置为异步:筛选操作是针对已经加载到内存的用户、待办列表执行,没有IO类耗时操作,同步执行即可完成。
- 不要把该逻辑放到导航层:数据关联属于业务逻辑,应该统一收敛在Bloc类中,保持逻辑分层清晰。
正确改造方案
步骤1:修改Bloc类逻辑
你已经在Bloc中加载了全量的用户和待办数据,只需要新增缓存存储全量待办,再提供根据用户ID筛选待办的方法即可,改造后代码如下:
class ApisBloc{ final _repos = Repositary(); final _usersFetcher = PublishSubject<List<Users>>(); final _todoUsers = PublishSubject<List<UsersToDos>>(); // 新增:缓存全量待办列表,用于后续筛选 List<UsersToDos> _allTodosCache = []; Stream<List<Users>> get allUsers => _usersFetcher.stream; Stream<List<UsersToDos>> get allTodos => _todoUsers.stream; fetchUsers() async{ List<Users> usersModels = await _repos.fetchUsers(); _usersFetcher.sink.add(usersModels); } fetchTodos() async{ List<UsersToDos> todo = await _repos.fetchTodosUsers(); // 加载待办时更新本地缓存 _allTodosCache = todo; _todoUsers.sink.add(todo); } dispose(){ _usersFetcher.close(); _todoUsers.close(); } // 改造后的筛选方法:传入用户ID,返回对应用户的待办列表 List<UsersToDos> findTodosByUserId(int userId){ // 假设待办实体类中有关联用户的userId字段,和用户的id字段对应 return _allTodosCache.where((todo) => todo.userId == userId).toList(); } } final bloc = ApisBloc();
步骤2:UI层调用
在用户列表的点击事件中直接调用Bloc的筛选方法,拿到对应用户的待办后传递给待办页面即可,示例代码如下:
// 用户列表渲染的StreamBuilder示例 StreamBuilder<List<Users>>( stream: bloc.allUsers, builder: (context, snapshot) { if (!snapshot.hasData) return const CircularProgressIndicator(); return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { final user = snapshot.data![index]; return ListTile( title: Text(user.name), onTap: () { // 点击用户时筛选对应待办 final userTodos = bloc.findTodosByUserId(user.id); // 跳转到待办页面,传递筛选后的待办数据 Navigator.push( context, MaterialPageRoute( builder: (context) => UserTodoPage(todos: userTodos), ), ); }, ); }, ); } )
可选优化方案
如果你的待办数据会有实时更新的需求,可以在Bloc中新增专门的当前用户待办流,点击用户时自动推送筛选后的待办,待办页面直接监听流做响应式渲染即可:
// Bloc内新增代码 final _currentUserTodos = PublishSubject<List<UsersToDos>>(); Stream<List<UsersToDos>> get currentUserTodos => _currentUserTodos.stream; void selectUser(int userId) { final filteredTodos = _allTodosCache.where((todo) => todo.userId == userId).toList(); _currentUserTodos.sink.add(filteredTodos); }
UI侧点击用户时调用bloc.selectUser(user.id),待办页面监听bloc.currentUserTodos流渲染列表即可。
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

