【问题标题】:How to call a function in cubit class in initState?如何在initState中调用cubit类中的函数?
【发布时间】: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,您可以从应用程序内的任何位置访问它。

标签: flutter bloc flutter-bloc flutter-state 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();
        },
      ),
    );
  }
}

【讨论】:

    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 2021-05-22
    • 2020-07-15
    • 2020-10-19
    相关资源
    最近更新 更多