所以,我在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>()),
}
),
}
有什么办法可以解决这个问题吗?
你可以尝试将
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"),
)
],
);
},
);
}),
),
);
}
}
当使用 Bloc 或 cubit 时,你不需要需要调用 initState 中的函数,只需在 BlocProvider 中创建 Cubit 时调用它即可,如下所示>>。
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(
/// after create the cubit you can call the method.
create: (context) => UsersCubit()..getAllUsers();,
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"),
)
],
);
},
),
),
);
}
}
您可以通过访问您的类来从您的 Blocprovider 调用它:-
BlocProvider(
create: (context) => Usercubit()..getAllUsers(),
build : (context) => Scaffold() ........
我在@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();
},
),
);
}
}
您可以轻松地做到这一点
UsersCubit() : super(UsersInitial()){getAllUsers();}
您的函数会在第一次加载“UsersPage”时自动运行。