【问题标题】:Flutter Bloc State Only Updates OnceFlutter Bloc 状态仅更新一次
【发布时间】:2022-08-11 15:11:07
【问题描述】:

问题是当用户尝试从 api 获取一些数据时,我想显示一个加载指示器。但是当用户按下按钮时,加载指示器会显示一次。但是我想每次用户尝试获取时都显示加载指示器。它有效,但正如我所说,它有效一次。谁能知道什么会导致这个问题?这是重现该问题的最少代码:

import \'package:flutter/material.dart\';
import \'package:flutter_bloc/flutter_bloc.dart\';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (_) => HomeCubit()),
      ],
      child: const MaterialApp(
        title: \'Flutter Bloc Demo\',
        home: HomeView(),
      ),
    );
  }
}

class HomeView extends BaseView<HomeCubit, HomeState> {
  const HomeView({Key? key}) : super(key: key);

  @override
  Widget builder(HomeCubit cubit, HomeState state) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(state.count.toString()),
          ElevatedButton(
            onPressed: cubit.increment,
            child: const Text(\'Increase\'),
          ),
        ],
      ),
    );
  }
}

class HomeState extends BaseState {
  final int count;

  HomeState({required this.count});

  HomeState copyWith({
    int? count,
  }) {
    return HomeState(
      count: count ?? this.count,
    );
  }
}

class HomeCubit extends BaseCubit<HomeState> {
  HomeCubit() : super(HomeState(count: 0));

  void increment() {
    flow(() async {
      await Future.delayed(const Duration(seconds: 1));

      emit(state.copyWith(count: state.count + 1));
    });
  }
}

@immutable
abstract class BaseView<C extends StateStreamable<S>, S extends BaseState>
    extends StatelessWidget {
  const BaseView({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) {
        return BaseCubit(context.read<S>());
      },
      child: Scaffold(
        body: BlocBuilder<C, S>(
          builder: (context, state) {
            final cubit = context.read<C>();

            if (state.loadingState == LoadingState.loading) {
              return loadingWidget;
            }

            return builder.call(cubit, state);
          },
        ),
      ),
    );
  }

  Widget builder(C cubit, S state);

  Widget get loadingWidget => const Center(
        child: CircularProgressIndicator(),
      );
}

enum LoadingState { initial, loading, loaded }

class BaseState {
  LoadingState loadingState;

  BaseState({
    this.loadingState = LoadingState.initial,
  });
}

class BaseCubit<S extends BaseState> extends Cubit<S> {
  BaseCubit(S state) : super(state);

  Future<void> flow(Future<void> Function() function) async {
    state.loadingState = LoadingState.loading;
    emit(state);

    await function();

    state.loadingState = LoadingState.loaded;
    emit(state);
  }
}

    标签: flutter dart bloc flutter-bloc


    【解决方案1】:
    1. 是否过度设计?如果您只使用 BlocBuilder 而不是某些基类,我认为您不会重复太多代码。
    2. 如果 bloc 已经存在,您应该通过 BlocProvider.value 而不是 BlocProvider(create: read()) 来提供它
    3. 您应该使用 context.watch 而不是 context.read 来在每次状态更改时获取一个新值。 context.read 只接收一次状态。
    4. 工程过度,请查看https://bloclibrary.dev/#/coreconcepts。有足够的教程来了解基本思想。
    5. 然后尝试使用 bloc + freezed。这是一个例子https://dev.to/ptrbrynt/why-bloc-freezed-is-a-match-made-in-heaven-29ai

    【讨论】:

      猜你喜欢
      • 2021-03-19
      • 2020-10-10
      • 2020-02-27
      • 2020-08-03
      • 2020-04-28
      • 2021-08-02
      • 2021-01-06
      • 2020-05-06
      • 2019-12-28
      相关资源
      最近更新 更多