Bloc 7.2.0版本中BlocSelector的使用方法及实际应用示例咨询
Bloc 7.2.0 版本 BlocSelector 组件使用说明
BlocSelector 是Bloc库提供的状态监听组件,核心作用是只监听Bloc/Cubit全量状态中的指定局部字段,仅当目标字段发生变化时才触发组件重绘,相比全量监听状态的BlocBuilder可以大幅减少不必要的渲染,提升页面性能。
基础参数说明
- 泛型参数从左到右依次为:目标Bloc/Cubit的类型、Bloc对应的全量状态类型、你筛选出的局部状态的类型
selector参数:接收全量状态作为入参,返回你需要监听的局部状态builder参数:接收上下文和筛选出的局部状态作为入参,返回对应渲染的Widget
实际使用示例
我们以用户信息管理场景为例,先定义对应的Cubit和状态类:
import 'package:bloc/bloc.dart'; import 'package:flutter/foundation.dart'; // 用户状态类 class UserState { final String username; final String avatarUrl; final String phone; const UserState({ required this.username, required this.avatarUrl, required this.phone, }); // 状态更新用copyWith UserState copyWith({ String? username, String? avatarUrl, String? phone, }) { return UserState( username: username ?? this.username, avatarUrl: avatarUrl ?? this.avatarUrl, phone: phone ?? this.phone, ); } // 重写==和hashCode保证状态变化可被检测 @override bool operator ==(Object other) => identical(this, other) || other is UserState && runtimeType == other.runtimeType && username == other.username && avatarUrl == other.avatarUrl && phone == other.phone; @override int get hashCode => username.hashCode ^ avatarUrl.hashCode ^ phone.hashCode; } // 对应的Cubit class UserCubit extends Cubit<UserState> { UserCubit() : super(const UserState(username: "游客", avatarUrl: "", phone: "")); // 更新用户名 void updateUsername(String newName) { emit(state.copyWith(username: newName)); } // 更新手机号 void updatePhone(String newPhone) { emit(state.copyWith(phone: newPhone)); } }
单字段监听示例
以下代码仅监听username字段变化,当调用updatePhone更新手机号时,该组件不会触发重绘:
BlocSelector<UserCubit, UserState, String>( selector: (state) => state.username, builder: (context, username) { return Text( "欢迎您:$username", style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ); }, )
多字段监听示例
如果需要同时监听多个字段,可以返回元组或者自定义的不可变对象:
// 同时监听用户名和头像两个字段 BlocSelector<UserCubit, UserState, (String, String)>( selector: (state) => (state.username, state.avatarUrl), builder: (context, userInfo) { return Row( children: [ // 展示头像,avatarUrl为空时展示默认占位图 userInfo.$2.isEmpty ? const Icon(Icons.account_circle, size: 40) : Image.network(userInfo.$2, width: 40, height: 40, fit: BoxFit.cover), const SizedBox(width: 12), Text(userInfo.$1), ], ); }, )
注意事项
- selector返回的状态必须是不可变的,如果返回自定义对象必须重写
==和hashCode,也可以直接使用equatable库自动生成对比逻辑,否则无法正确检测状态变化 - 不建议在selector中做复杂计算,该函数会在每次全量状态更新时执行,复杂计算会影响性能
- 如果需要监听全量状态的变化,直接使用
BlocBuilder即可,不需要用BlocSelector
内容的提问来源于stack exchange,提问作者Mariam Albarghouti
相关产品推荐
相关产品推荐

