bloc从3.x升级至8.0.1出现弃用报错的代码适配方案咨询
Bloc 8.0.1 适配改造方案
Bloc 8.x 版本已完全移除旧版mapEventToStateAPI,所有事件处理逻辑需要迁移到构造函数的on<Event>注册回调中,同时需要补全状态/事件的相等判断逻辑、管理异步订阅资源,具体改造步骤如下:
1. 改造 player_event.dart
原代码中PlayEvent的props为空,会导致Bloc无法区分携带不同电台参数的播放事件,需要将参数加入props列表:
part of 'player_bloc.dart'; @immutable abstract class PlayerEvent extends Equatable { const PlayerEvent(); @override List<Object> get props => []; } class PlayEvent extends PlayerEvent { final Station station; PlayEvent(this.station); @override List<Object> get props => [station]; // 补全属性,保证事件相等判断正常 } class PauseEvent extends PlayerEvent {}
2. 改造 player_state.dart
原代码中PlayingState、PausedState的props为空,会导致同类型不同参数的状态被判定为相等,出现UI不更新的问题,需要补全props:
part of 'player_bloc.dart'; @immutable abstract class PlayerState extends Equatable { const PlayerState(); @override List<Object> get props => []; } class StoppedState extends PlayerState {} class PlayingState extends PlayerState { final Station currentStation; PlayingState(this.currentStation); @override List<Object> get props => [currentStation]; // 补全属性 } class PausedState extends PlayerState { final Station currentStation; PausedState(this.currentStation); @override List<Object> get props => [currentStation]; // 补全属性 }
3. 重构 player_bloc.dart
需要删除废弃的mapEventToState重写方法,迁移逻辑到on回调,同时管理流订阅避免内存泄漏,修正异步执行顺序:
import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:meta/meta.dart'; import 'package:online_radio/radio/radio_player.dart'; import 'package:online_radio/radio/radio_state.dart'; import 'package:online_radio/station.dart'; part 'player_event.dart'; part 'player_state.dart'; class PlayerBloc extends Bloc<PlayerEvent, PlayerState> { final RadioPlayer radioPlayer; // 存储电台状态流订阅,Bloc销毁时需要取消 late final StreamSubscription _radioStateSubscription; PlayerBloc({@required this.radioPlayer}) : assert(radioPlayer != null), super(StoppedState()) { // 注册播放事件处理逻辑 on<PlayEvent>((event, emit) async { final currentState = state; if (currentState is StoppedState) { await _playNewRadioStation(event); emit(PlayingState(event.station)); } else if (currentState is PausedState) { if (currentState.currentStation != event.station) { await _playNewRadioStation(event); } else { _playExistingRadioStation(); } emit(PlayingState(event.station)); } else if (currentState is PlayingState) { if (currentState.currentStation != event.station) { await _playNewRadioStation(event); } else { _playExistingRadioStation(); } emit(PlayingState(event.station)); } }); // 注册暂停事件处理逻辑 on<PauseEvent>((event, emit) { final currentState = state; if (currentState is PlayingState) { radioPlayer.pause(); emit(PausedState(currentState.currentStation)); } }); // 初始化电台原生状态监听 _radioStateSubscription = radioPlayer.radioStateStream.listen((radioState) { if (radioState == RadioState.PLAYING && state is PausedState) { add(PlayEvent((state as PausedState).currentStation)); } }); } // 重写close方法,释放订阅资源 @override Future<void> close() { _radioStateSubscription.cancel(); return super.close(); } void _playExistingRadioStation() { radioPlayer.play(); } // 改为async/await写法,保证音频地址设置完成后再触发播放 Future<void> _playNewRadioStation(PlayEvent playEvent) async { await radioPlayer.setUrl(playEvent.station.radioUrl); radioPlayer.play(); } }
核心改动说明
- 完全移除Bloc 8.x已删除的
mapEventToState方法,所有事件处理统一使用on<Event>注册,使用回调提供的emit方法派发状态,替代旧版yield语法 - 补全所有Event、State子类的props列表,避免Equatable相等判断失效导致的事件不响应、UI不刷新问题
- 对原生播放器的状态流订阅做生命周期绑定,Bloc关闭时自动取消订阅,避免内存泄漏和空回调异常
- 修正切歌逻辑的异步顺序,等待音频地址设置完成后再派发播放状态,避免播放异常
内容的提问来源于stack exchange,提问作者aneebhiba614
相关产品推荐
相关产品推荐

