如何在initState中调用cubit类中的函数?

问题描述 投票:0回答:5

所以,我在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>()),
      }
    ),
  }

有什么办法可以解决这个问题吗?

flutter bloc flutter-bloc flutter-state cubit
5个回答
6
投票

你可以尝试将

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"),
                  )
                ],
              );
            },
          );
        }),
      ),
    );
  }
}


6
投票

当使用 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"),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}

5
投票

您可以通过访问您的类来从您的 Blocprovider 调用它:-

 BlocProvider(
      create: (context) => Usercubit()..getAllUsers(),
      build : (context) => Scaffold() ........
    

1
投票

我在@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();
        },
      ),
    );
  }
}

0
投票

您可以轻松地做到这一点

UsersCubit() : super(UsersInitial()){getAllUsers();}
您的函数会在第一次加载“UsersPage”时自动运行。

© www.soinside.com 2019 - 2024. All rights reserved.