如何使用 flutter bloc 在同一屏幕上管理多个状态

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

我有一个带有三个小部件的屏幕 [widgetA、widgetB、widgetC] 我有一个 bloc[BlocA] 负责数据获取并在该屏幕上显示 我有三个事件 [eventA、eventB、eventC],它们渲染小部件 [widgetA、widgetB、widgetC] 我有三个状态 [stateA,stateB,stateC] 负责管理小部件的状态 [widgetA,widgetB,widgetC] 我已附上所有代码来重现和测试该案例。

我一次只能显示一种状态及其各自的小部件,而我想根据它们的事件显示所有三种状态及其小部件。 任何帮助将不胜感激。

我尝试实现相同目标的唯一方法是为每个小部件创建单独的块和事件类,但不知何故我对这种方法不满意。

实现此用例的最佳方法是什么。

测试屏幕

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:locus/blocs/test/testbloc.dart';

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

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
        create: (context) => TestBloc()..add(const TestEvent1()),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Test'),
          ),
          body: Stack(
            children: [
              Builder(builder: (context) {
                return Padding(
                  padding: const EdgeInsets.only(top: 0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                          onPressed: () =>
                              context.read<TestBloc>().add(const TestEvent1()),
                          child: const Text("Event1")),
                      const SizedBox(width: 10),
                      ElevatedButton(
                          onPressed: () => context
                              .read<TestBloc>()
                              .add(const TestEvent2(" event 2")),
                          child: const Text("Event2")),
                      const SizedBox(width: 10),
                      ElevatedButton(
                          onPressed: () => context
                              .read<TestBloc>()
                              .add(const TestEvent3(false)),
                          child: const Text("Event3")),
                    ],
                  ),
                );
              }),
              BlocBuilder<TestBloc, TestState>(
                builder: (context, state) {
                  if (state is TestState1) {
                    return const Center(child: Text("I am state 1"));
                  }
                  return const SizedBox.shrink();
                },
              ),
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  BlocBuilder<TestBloc, TestState>(
                    builder: (context, state) {
                      if (state is TestState2) {
                        return Center(
                            child: Text("I am state 2 ${state.message}"));
                      }
                      return const SizedBox.shrink();
                    },
                  ),
                  BlocBuilder<TestBloc, TestState>(
                    builder: (context, state) {
                      if (state is TestState3) {
                        return Center(
                            child: Text("I am state 3 ${state.check}"));
                      }
                      return const SizedBox.shrink();
                    },
                  ),
                ],
              ),
            ],
          ),
        ));
  }
}

测试块


import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:bloc/bloc.dart';
part 'test_state.dart';
part 'test_event.dart';

class TestBloc extends Bloc<TestEvent, TestState> {
  TestBloc() : super(TestInitializing()) {
    on<TestEvent1>((event, emit) => test1(event, emit));
    on<TestEvent2>((event, emit) => test2(event, emit));
    on<TestEvent3>((event, emit) => test3(event, emit));
  }

  Future test1(TestEvent1 event, Emitter<TestState> emit) async {
    try {
      emit(const TestState1());
    } catch (_) {}
  }

  Future test2(TestEvent2 event, Emitter<TestState> emit) async {
    try {
      emit(const TestState2(message: "Hello"));
    } catch (_) {}
  }

  Future test3(TestEvent3 event, Emitter<TestState> emit) async {
    try {
      emit(const TestState3(check: true));
    } catch (_) {}
  }
}

测试事件


@immutable
abstract class TestEvent extends Equatable {
  const TestEvent();
}

class TestEvent1 extends TestEvent {
  const TestEvent1();
  @override
  List<Object> get props => [];
}

class TestEvent2 extends TestEvent {
  final String message;
  const TestEvent2(this.message);
  @override
  List<Object> get props => [message];
}

class TestEvent3 extends TestEvent {
  final bool check;
  const TestEvent3(this.check);
  @override
  List<Object> get props => [check];
}

测试状态


@immutable
abstract class TestState extends Equatable {
  const TestState();
}

class TestInitializing extends TestState {
  @override
  List<Object> get props => [];
}

class TestState1 extends TestState {
  const TestState1();
  @override
  List<Object?> get props => [];
}

class TestState2 extends TestState {
  final String message;
  const TestState2({
    required this.message,
  });
  @override
  List<Object> get props => [message];
}

class TestState3 extends TestState {
  final bool check;
  const TestState3({
    required this.check,
  });
  @override
  List<Object> get props => [check];
}

testbloc 桶类

export 'test_bloc.dart';
flutter bloc flutter-bloc flutter-state
4个回答
7
投票

一个集团一次只能有一个州。如果您想要更多的状态,则必须在 TestBloc 内维护自定义内部状态机制,或者创建 3 个单独的 TestBloc,然后为每个 BlocBuilder 提供每个 TestBloc,如下所示:

class TestScreen extends StatelessWidget {
  TestScreen({Key? key}) : super(key: key) {
  }

  final TestBloc bloc1 = TestBloc();
  final TestBloc bloc2 = TestBloc();
  final TestBloc bloc3 = TestBloc();

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
        create: (context) => TestBloc()..add(const TestEvent1()),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Test'),
          ),
          body: Stack(
            children: [
              Builder(builder: (context) {
                return Padding(
                  padding: const EdgeInsets.only(top: 0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                          onPressed: () =>
                              bloc1.add(const TestEvent1()),
                          child: const Text("Event1")),
                      const SizedBox(width: 10),
                      ElevatedButton(
                          onPressed: () => bloc2.add(const TestEvent2(" event 2")),
                          child: const Text("Event2")),
                      const SizedBox(width: 10),
                      ElevatedButton(
                          onPressed: () => bloc3.add(const TestEvent3(false)),
                          child: const Text("Event3")),
                    ],
                  ),
                );
              }),
              BlocBuilder<TestBloc, TestState>(
                bloc: bloc1,
                builder: (context, state) {
                  if (state is TestState1) {
                    return const Center(child: Text("I am state 1"));
                  }
                  return const SizedBox.shrink();
                },
              ),
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  BlocBuilder<TestBloc, TestState>(
                    bloc: bloc2,
                    builder: (context, state) {
                      if (state is TestState2) {
                        return Center(
                            child: Text("I am state 2 ${state.message}"));
                      }
                      return const SizedBox.shrink();
                    },
                  ),
                  BlocBuilder<TestBloc, TestState>(
                    bloc: bloc3,
                    builder: (context, state) {
                      if (state is TestState3) {
                        return Center(
                            child: Text("I am state 3 ${state.check}"));
                      }
                      return const SizedBox.shrink();
                    },
                  ),
                ],
              ),
            ],
          ),
        ));
  }
}

然而,就关注点分散而言,制作 3 个独立的块(TestBloc1、TestBloc2、TestBloc3)不一定是一个坏方法。


1
投票

我参加聚会已经很晚了,但我已经实现了一个完全符合您想要的功能的软件包!

给你:https://pub.dev/packages/multi_state_bloc


1
投票

您可以尝试以下代码:

buildWhen: (previous, current) => current is TestState1 && previous != current.

0
投票

您可以使用 build when 它将根据约束构建特定状态 这是用法示例

国家级

 class GetAllVariantsLoading extends FilterState {}

class GetAllVariantsFailure extends FilterState {
  final String errorMessage;

  GetAllVariantsFailure(this.errorMessage);
}

class GetAllVariantsSuccess extends FilterState {
  final AllVariantsResponse getAllVariantsResponse;
  final List<VariantValuesModel> allValues;

  GetAllVariantsSuccess(this.getAllVariantsResponse, this.allValues);
}

用户界面

@override

小部件构建(BuildContext上下文){ 最终块= Modular.get();

return BlocBuilder<FilterBloc, FilterState>(
  buildWhen: (previous, current) {
    return current is GetAllVariantsLoading ||
        current is GetAllVariantsFailure ||
        current is GetAllVariantsSuccess;
  },
  bloc: bloc,
  builder: (context, state) {
    if (state is GetAllVariantsLoading) {
      return _buildLoading();
    } else if (state is GetAllVariantsFailure) {
      return _buildFailure(state);
    } else if (state is GetAllVariantsSuccess) {
      return  class GetAllVariantsLoading extends FilterState {}

class GetAllVariantsFailure extends FilterState {
  final String errorMessage;

  GetAllVariantsFailure(this.errorMessage);
}

class GetAllVariantsSuccess extends FilterState {
  final AllVariantsResponse getAllVariantsResponse;
  final List<VariantValuesModel> allValues;

  GetAllVariantsSuccess(this.getAllVariantsResponse, this.allValues);
}_buildSuccess(state, bloc);
    }  else {
      return  PleaseTryAgainMessage(
        title: state.toString(),
        callback:  () => bloc.add(GetAllVariantsEvent()),
      );
    }
  },
);

}

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