【问题标题】:Flutter bloc - do not call the api every time (use the same State in different views)Flutter bloc - 不要每次都调用 api(在不同视图中使用相同的 State)
【发布时间】:2021-09-24 17:55:47
【问题描述】:

我在我的颤振应用程序中使用颤振 bloc 模式。我有一页中有几个标签的底部导航栏。其中两个使用相同的 api 调用(相同的状态)。当用户点击其中一个时,我调用 api 来获取数据,但是如果用户点击另一个选项卡,我想在不再次调用 api 的情况下获取数据。我该怎么做?

在我的主页(仪表板)中,我有 BlocBuilder 来更改选项卡,并在其中创建仪表板 cubit

class DashboardPage extends StatelessWidget {

 @override
 Widget build(BuildContext context) {
   return BlocBuilder<TabsBloc, AppTab>(
     builder: (BuildContext context, AppTab activeTab) {
       return Scaffold(
         appBar: AppBar(
           title: Text(DashboardHelpers.getTabLabel(activeTab)),
         ),
         body: RepositoryProvider(
           create: (BuildContext context) => DashboardRepository(),
           child: BlocProvider<DashboardCubit>(
             create: (BuildContext context) => DashboardCubit(
               dashboardRepository: context.read<DashboardRepository>(),
               authBloc: context.read<AuthBloc>(),
             ),
             child: DashboardHelpers.getTabContent(activeTab),
           ),
         ),
         bottomNavigationBar: TabSelector(
             activeTab: activeTab,
             onTabSelected: (tab) =>
                 BlocProvider.of<TabsBloc>(context).add(TabUpdated(tab))),
       );
     },
   );
 }
}

标签是作为子加载的视图。其中一个视图是 View1。当我得到我在 ContentView1 中加载的数据时

class View1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    BlocProvider.of<DashboardCubit>(context)..getDashboardDevices();
    return BlocConsumer<DashboardCubit, DashboardState>(
      listener: (BuildContext context, DashboardState state) {
        if (state is DashboardError) {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              content: Text(state.message),
            ),
          );
        }
      },
      builder: (BuildContext context, DashboardState state) {
        if (state is DevicesLoaded) {
          return ContentView1(data: state.data);
        } else if (state is DashboardLoading) {
          return LoadingWidget();
        } else if (state is DashboardError) {
          return Container(
            child: Center(
              child: Text(state.message),
            ),
          );
        } else {
          return Container();
        }
      },
    );
  }
}

和 View2 几乎一样。数据是完全一样的,它是在 ContentView2 中加载的,但它是一个与 ContentView1 完全不同的小部件

class View2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    BlocProvider.of<DashboardCubit>(context)..getDashboardDevices();
    return BlocConsumer<DashboardCubit, DashboardState>(
      listener: (BuildContext context, DashboardState state) {
        if (state is DashboardError) {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              content: Text(state.message),
            ),
          );
        }
      },
      builder: (BuildContext context, DashboardState state) {
        if (state is DevicesLoaded) {
          return ContentView2(data: state.data);
        } else if (state is DashboardLoading) {
          return LoadingWidget();
        } else if (state is DashboardError) {
          return Container(
            child: Center(
              child: Text(state.message),
            ),
          );
        } else {
          return Container();
        }
      },
    );
  }
}

问题在于这两个视图显示来自同一 API 端点的不同数据。 当用户从 View1 切换到 View2 时,如何在不再次调用 API 的情况下加载已经获取的数据。

谢谢!

【问题讨论】:

    标签: flutter bloc flutter-bloc


    【解决方案1】:

    你应该只调用一次getDashboardDevices(),因为你可以创建一个DashboardInitialState,当用户点击一个选项卡时,如果状态是DashboardInitialState你运行getDashboardDevices()而不是总是在视图构建时.这样,您将只在构建其中一个视图时加载一次数据,并且它们都将在加载状态下使用相同的数据。

    以 View1 为例,尝试使用两个视图:

    class View1 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return BlocConsumer<DashboardCubit, DashboardState>(
          listener: (BuildContext context, DashboardState state) {
            if (state is DashboardError) {
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  content: Text(state.message),
                ),
              );
            }
          },
          builder: (BuildContext context, DashboardState state) {
            if(state is DashboardInitialState) {
              BlocProvider.of<DashboardCubit>(context)..getDashboardDevices();
              return LoadingWidget();
            } else if (state is DevicesLoaded) {
              return ContentView1(data: state.data);
            } else if (state is DashboardLoading) {
              return LoadingWidget();
            } else if (state is DashboardError) {
              return Container(
                child: Center(
                  child: Text(state.message),
                ),
              );
            } else {
              return Container();
            }
          },
        );
      }
    }
    
    

    【讨论】:

    • 这很接近,但从未想过。谢谢!
    猜你喜欢
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多