Flutter Bloc - Flutter Bloc 状态未更新
Posted
技术标签:
【中文标题】Flutter Bloc - Flutter Bloc 状态未更新【英文标题】:Flutter Bloc - Flutter Bloc state not updating 【发布时间】:2021-03-19 05:30:32 【问题描述】:我刚刚开始使用颤振集团。 我尝试制作状态,但它总是进入初始状态。有什么解决办法?
集团
class VisiMisiBloc extends Bloc<VisiMisiEvent, VisiMisiState>
VisiMisiBloc(this.visiMisiRepository) : super(VisiMisiInitial());
final VisiMisiRepository visiMisiRepository;
@override
Stream<VisiMisiState> mapEventToState(VisiMisiEvent event) async*
if (event is GetVisiMisiList)
yield* _getVisiMisi(event, state);
Stream<VisiMisiState> _getVisiMisi(VisiMisiEvent event, VisiMisiState state) async*
yield VisiMisiLoading();
try
ResponseModel<VisiMisiModel> response = await visiMisiRepository.getVisiMisi();
print(response);
if (response.statusCode == 0)
int insertedId = await visiMisiRepository.insertVisiMisi(response.data);
print(insertedId);
List<VisiMisiModel> visiMisiList = await visiMisiRepository.getAllVisiMisi();
yield VisiMisiLoaded(visiMisiList);
else
yield VisiMisiError(response.errorMessage);
on Exception catch (e)
yield VisiMisiError(e.toString());
状态
part of 'visi_misi_bloc.dart';
abstract class VisiMisiState extends Equatable
const VisiMisiState();
class VisiMisiInitial extends VisiMisiState
const VisiMisiInitial();
@override
List<Object>get props => [];
class VisiMisiLoading extends VisiMisiState
const VisiMisiLoading();
@override
List<Object>get props => [];
class VisiMisiLoaded extends VisiMisiState
final List<VisiMisiModel> visiMisiModel;
const VisiMisiLoaded(this.visiMisiModel);
@override
List<Object> get props => [visiMisiModel];
class VisiMisiError extends VisiMisiState
final String message;
const VisiMisiError(this.message);
@override
List<Object>get props => [message];
活动
part of 'visi_misi_bloc.dart';
abstract class VisiMisiEvent extends Equatable
const VisiMisiEvent();
class GetVisiMisiList extends VisiMisiEvent
@override
List<Object> get props => [];
存储库
abstract class VisiMisiRepository
Future<int> insertVisiMisi(VisiMisiModel todo);
Future<ResponseModel<VisiMisiModel>> getVisiMisi();
Future<List<VisiMisiModel>> getAllVisiMisi();
存储库实现
class VisiMisiRepositoryImpl extends VisiMisiRepository
final NetworkInfoImpl networkInfo;
final RemoteDataSource remoteDatasource;
final VisiMisiDao dao;
VisiMisiRepositoryImpl(this.networkInfo, this.remoteDatasource, this.dao);
@override
Future<ResponseModel<VisiMisiModel>> getVisiMisi()
return remoteDatasource.visiMisi();
@override
Future<int> insertVisiMisi(VisiMisiModel todo)
return dao.upsert(todo);
@override
Future<List<VisiMisiModel>> getAllVisiMisi()
return dao.getAll(userTABLE, VisiMisiModel.fromJson);
远程数据源
Future<ResponseModel<VisiMisiModel>> visiMisi() async
SharedPreferences prefs = await SharedPreferences.getInstance();
String auth_token = prefs.getString("auth_token");
try
final response = await httpClient.get(ServiceUrl.visiMisi, auth_token);
if(response.statusCode != 200)
throw new Exception('Error getting visi misi');
return ResponseModel<VisiMisiModel>.fromJson(response, VisiMisiModel.fromJson);
catch(e)
print(e);
查看
class VisiMisiPage extends StatefulWidget
@override
_VisiMisiPageState createState() => _VisiMisiPageState();
class _VisiMisiPageState extends State<VisiMisiPage>
VisiMisiRepository repository;
@override
void initState()
super.initState();
@override
Widget build(BuildContext context)
return SafeArea(
child: Scaffold(
backgroundColor: AppColor.white,
appBar: AppBar(
title: Text("VISI & MISI", style: TextStyle(fontSize: 16, color: AppColor.deepCerulean),),
backgroundColor: Colors.white,
elevation: 0,
automaticallyImplyLeading: false,
brightness: Brightness.light,
leading: IconButton(
icon: new Icon(Icons.arrow_back, color: AppColor.deepCerulean,),
onPressed: () => Navigator.of(context).pop(),
),
),
body: BlocProvider<VisiMisiBloc>(
create: (_) => VisiMisiBloc(repository),
child: BlocBuilder<VisiMisiBloc, VisiMisiState>(
builder: (context, state)
if (state is VisiMisiInitial)
//BlocProvider.of<VisiMisiBloc>(context).add(GetVisiMisiList());
return Center(child: Text(state.toString()),);
else if (state is VisiMisiLoading)
return Center(child: CircularProgressIndicator(),);
else if (state is VisiMisiLoaded)
return SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_visiWidget(context, state),
SizedBox(height: 20,),
_misiWidget(context),
SizedBox(height: 30,),
_footerWidget(context)
],
),
),
);
else if (state is VisiMisiError)
return Center(child: Text(state.message),);
)
),
)
);
void _onWidgetDidBuild(Function callback)
WidgetsBinding.instance.addPostFrameCallback((_)
callback();
);
我得到一个未处理的异常:未处理的错误 NoSuchMethodError:方法 'getVisiMisi' 在 null 上被调用。
在视图中,状态显示在 VisiMisiInitial 中,并且不想更新到 VisiMisiLoading
【问题讨论】:
【参考方案1】:我分析了你的代码,发现了2个错误:
1st.您刚刚创建了 VisiMisiRepository 的实例,但尚未初始化。你正在调用他们的方法,这就是为什么你会收到错误Unhandled error NoSuchMethodError: The method 'getVisiMisi' was called on null.
第二次。您刚刚在传递的存储库实例中初始化了您的 bloc,并且还没有执行任何 bloc 事件。这就是代码一直显示初始状态的原因。
您可能已经得到了答案。 如果没有,请从这里寻求帮助,它一定会对您有所帮助:
替换这个:
create: (_) => VisiMisiBloc(repository),
用这个:
create: (_) => VisiMisiBloc(VisiMisiRepository())..add(GetVisiMisiList()),
在您的小部件树中:
body: BlocProvider<VisiMisiBloc>(
create: (_) => VisiMisiBloc(VisiMisiRepository())..add(GetVisiMisiList()), //initialising bloc within repository and hit event as well.
child: BlocBuilder<VisiMisiBloc, VisiMisiState>(
builder: (context, state)
if (state is VisiMisiInitial)
return Center(child: Text(state.toString()),);
else if (state is VisiMisiError)
return Center(child: Text(state.message),);
else if (state is VisiMisiLoaded)
return SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_visiWidget(context, state),
SizedBox(height: 20,),
_misiWidget(context),
SizedBox(height: 30,),
_footerWidget(context)
],
),
),
);
return Center(child: CircularProgressIndicator(),);
)
),
这个答案也将解决Unhandled error NoSuchMethodError: The method 'getVisiMisi' was called on null
错误。
【讨论】:
【参考方案2】:要初始化存储库,您应该使用 RepositoryProvider。
例如,类似的东西
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MultiRepositoryProvider(
providers: [
RepositoryProvider<UserRepository>(
create: (context) => UserRepository(),
),
],
child: MultiBlocProvider(
providers: [
BlocProvider<LoginBloc>(
create: (context) => LoginBloc(context.read<UserRepository>()),
),
],
child: Widget()));
然后会自动初始化
【讨论】:
【参考方案3】:尝试像这样初始化存储库:
class _VisiMisiPageState extends State<VisiMisiPage>
VisiMisiRepository repository;
@override
void initState()
super.initState();
repository = VisiMisiRepositoryImpl( parameters here ); // add this one
【讨论】:
以上是关于Flutter Bloc - Flutter Bloc 状态未更新的主要内容,如果未能解决你的问题,请参考以下文章
flutter_bloc 库中的存储库提供程序在推送新路由时不提供存储库
谁能说出 Flutter 中“flutter_bloc”和“bloc”包的区别