如何在initState中调用cubit类中的函数?
Posted
技术标签:
【中文标题】如何在initState中调用cubit类中的函数?【英文标题】:How to call a function in cubit class in initState? 【发布时间】:2021-12-17 11:21:29 【问题描述】:所以,我在 Cubit 类中做了一个函数,它是从 API 获取数据。现在,如果我按下一个按钮,我就可以获得数据。我想在页面/屏幕打开时自动调用该功能。供您参考,此页面是用户打开应用程序时将启动的第一个页面。这是我的一些代码。
class UsersCubit extends Cubit<UsersState>
UsersCubit() : super(UsersInitial());
UserRepository _userRepository = UserRepository();
void getAllUsers() async
emit(UsersLoading());
try
ResponseUsers _data = await _userRepository.getUsers();
emit(UsersSuccess(_data));
catch(e)
emit(UsersError(e.toString()));
class UsersPage extends StatefulWidget
const UsersPage(Key? key) : super(key: key);
@override
_UsersPageState createState() => _UsersPageState();
class _UsersPageState extends State<UsersPage>
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(title: Text("Users")),
body: BlocProvider(
create: (context) => UsersCubit(),
child: BlocConsumer<UsersCubit, UsersState>(
listener: (context, state)
if(state is UsersLoading)
print("getting users ...");
else if (state is UsersSuccess)
print(state.data.users[1].identity!.name);
else if (state is UsersError)
print(state.errorMessage);
,
builder: (context, state)
return Stack(
children: [
(state is UsersSuccess) ? listViewUsers(state.data.users) : progressBar(),
ElevatedButton(
onPressed: ()
context.read<UsersCubit>().getAllUsers();
,
child: Text("GET USERS"),
)
],
);
,
),
),
);
我曾尝试直接在initState
中调用该函数,但是当我运行该应用程序时它会返回错误。
@override
void initState()
context.read<UsersCubit>().getAllUsers();
super.initState();
错误:
Error: Could not find the correct Provider<UsersCubit> above this UsersPage Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that UsersPage is under your MultiProvider/Provider<UsersCubit>.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
...
Widget build(BuildContext context)
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
...
consider using `builder` like so:
...
Widget build(BuildContext context)
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context)
// No longer throws
return Text(context.watch<Example>()),
),
有什么办法可以解决这个问题吗?
【问题讨论】:
你能分享你的代码吗?哪个有 BlocProvider for UsersCubit 和 class 使用这个 Cubit ? 由于您使用的是 Cubit,因此您被锁定在 BloC 中。如此简短的回答:我帮不了你。更长的答案:如果 BloC 是您与 Flutter 一起使用的 ONLY 状态管理,那么 PLEASE 考虑替代方法。很多时候,你不需要比StatefulWidget 更复杂的东西。你SELDOM需要比Provider更复杂的东西。 Flutter 提供了很多 - 很棒! - 选择。使用“工作的最佳工具”:) PS:when I run the app it returns an error...
:请更新您的帖子,提供准确的错误信息!
我已经更新了@dangngocduc 的帖子
在MaterialApp
上方提供您的cubit,您可以从应用程序内的任何位置访问它。
【参考方案1】:
您可以尝试将BlocConsumer
包裹在Builder
中吗?
import 'package:flutter/material.dart';
class UsersPage extends StatefulWidget
const UsersPage(Key? key) : super(key: key);
@override
_UsersPageState createState() => _UsersPageState();
class _UsersPageState extends State<UsersPage>
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(title: Text("Users")),
body: BlocProvider(
create: (context)
final cubit = UsersCubit();
cubit.getAllUsers();
return cubit;
,
child: Builder(builder: (context)
return BlocConsumer<UsersCubit, UsersState>(
listener: (context, state)
if(state is UsersLoading)
print("getting users ...");
else if (state is UsersSuccess)
print(state.data.users[1].identity!.name);
else if (state is UsersError)
print(state.errorMessage);
,
builder: (context, state)
return Stack(
children: [
(state is UsersSuccess) ? listViewUsers(state.data.users) : progressBar(),
ElevatedButton(
onPressed: ()
context.read<UsersCubit>().getAllUsers();
,
child: Text("GET USERS"),
)
],
);
,
);
),
),
);
【讨论】:
我刚试了一下,还是一样的错误 我刚刚更新了解决方案,你可以再试试我的代码吗? 这个案子已经解决了:)【参考方案2】:我在@Ehsan Askari 的帮助下解决了这个问题。他建议我提供MaterialApp上方的肘部,然后我就做了。这是我现在的代码
class AppWidget extends StatelessWidget
// This widget is the root of your application.
@override
Widget build(BuildContext context)
return BlocProvider(
create: (context) => UsersCubit(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: UsersPage(),
),
);
class UsersPage extends StatefulWidget
const UsersPage(Key? key) : super(key: key);
@override
_UsersPageState createState() => _UsersPageState();
class _UsersPageState extends State<UsersPage>
@override
void initState()
context.read<UsersCubit>().getAllUsers();
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(title: Text("Users")),
body: BlocConsumer<UsersCubit, UsersState>(
listener: (context, state)
if(state is UsersLoading)
print("getting users ...");
else if (state is UsersSuccess)
print(state.data.users[1].identity!.name);
else if (state is UsersError)
print(state.errorMessage);
,
builder: (context, state)
return (state is UsersSuccess) ? listViewUsers(state.data.users) : progressBar();
,
),
);
【讨论】:
以上是关于如何在initState中调用cubit类中的函数?的主要内容,如果未能解决你的问题,请参考以下文章
如何在使用 pop 时重新加载或调用一些函数 initState()
Flutter BLoC 库:将 TextEditingController 对象保存在哪里:在 State、BLoC / Cubit 类中还是在小部件中?