dart 触发BLoC中的初始事件

pcww981p  于 2022-12-15  发布在  其他
关注(0)|答案(3)|浏览(112)

示例_状态:

abstract class ExampleState extends Equatable {
  const ExampleState();
}

class LoadingState extends ExampleState {
  //
}

class LoadedState extends ExampleState {
  //
}

class FailedState extends ExampleState {
  //
}

事件示例:

abstract class ExampleEvent extends Equatable {
  //
}

class SubscribeEvent extends ExampleEvent {
  //
}

class UnsubscribeEvent extends ExampleEvent {
  //
}

class FetchEvent extends ExampleEvent {
  // 
}

示例块:

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  @override
  ExampleState get initialState => LoadingState();

  @override
  Stream<ExampleState> mapEventToState(
    ExampleEvent event,
  ) async* {
    if (event is SubscribeEvent) {
      //
    } else if (event is UnsubscribeEvent) {
      //
    } else if (event is FetchEvent) {
      yield LoadingState();
      try {
        // network calls
        yield LoadedState();
      } catch (_) {
        yield FailedState();
      }
    }
  }
}

示例屏幕:

class ExampleScreenState extends StatelessWidget {
  // ignore: close_sinks
  final blocA = ExampleBloc();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<ExampleBloc, ExampleState>(
        bloc: blocA,
        // ignore: missing_return
        builder: (BuildContext context, state) {
          if (state is LoadingState) {
            blocA.add(Fetch());
            return CircularProgressBar();
          }

          if (state is LoadedState) {
            //...
          }

          if (state is FailedState) {
            //...
          }
        },
      ),
    );
  }
}

正如你在example_bloc中看到的,初始状态是LoadingState(),在构建中它显示循环进度条。我使用Fetch()事件来触发下一个状态。但是我觉得在那里使用它不舒服。我想做的是:
当应用程序启动时,它应该显示LoadingState并开始网络调用,然后当它全部完成时,它应该显示LoadedState和网络调用结果,如果出现错误,它应该显示FailedState。

if (state is LoadingState) {
  blocA.add(Fetch());
  return CircularProgressBar();
}
sbtkgmzw

sbtkgmzw1#

您的不适确实是有原因的-不应该从build()方法中触发任何事件(build()可以根据Flutter框架的需要被触发多次)
我们的案例是在创建集团时触发初始事件
可能性概述
1.使用BlocProvider插入Bloc的情况-这是首选方法
create:回调仅在装载BlocProvider时触发一次,并且在卸载BlocProvider时BlocProvider将close()block

class ExampleScreenState extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: BlocProvider(
            create: (context) => ExampleBloc()..add(Fetch()), // <-- first event, 
            child: BlocBuilder<ExampleBloc, ExampleState>(
              builder: (BuildContext context, state) {
                ...
              },
            ),
          ),
        );
      }
    }

1.在Statefull小部件的State中创建Bloc时的情况

class _ExampleScreenStateState extends State<ExampleScreenState> {
  ExampleBloc _exampleBloc;

  @override
  void initState() {
    super.initState();
    _exampleBloc = ExampleBloc();
    _exampleBloc.add(Fetch());
    // or use cascade notation
    // _exampleBloc = ExampleBloc()..add(Fetch());
  }

  @override
  void dispose() {
    super.dispose();
    _exampleBloc.close(); // do not forget to close, prefer use BlocProvider - it would handle it for you
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<ExampleBloc, ExampleState>(
        bloc: _exampleBloc,
        builder: (BuildContext context, state) {
         ...
        },
      ),
    );
  }
}

1.在Bloc示例创建时添加第一个事件-这种方式在测试时有缺点,因为第一个事件是隐式的

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {

  ...

  ExampleBloc() {
    add(Fetch());
  }
}

// insert it to widget tree with BlocProvider or create in State
BlocProvider( create: (_) => ExampleBloc(), ...

// or in State

class _ExampleScreenStateState extends State<ExampleScreenState> {
  final _exampleBloc = ExampleBloc(); 
...

PS随时联系我的评论

mfuanj7w

mfuanj7w2#

Sergey Salnikov有一个很好的答案,但是我想我可以补充另一个建议。
在我的主.dart文件中,我使用MultiBlocProvider创建所有的块,以便在树中进一步使用。

Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: <BlocProvider<dynamic>>[
        BlocProvider<OneBloc>(create: (_) => OneBloc()),
        BlocProvider<TwoBloc>(create: (_) => TwoBloc()),
      ],
      child: MaterialApp( // Rest of your app )

字符串
然后,当我需要在加载页面时调用一个事件时,在本例中,我希望根据所选的列表块获取一些数据,并且我需要比FutureBuilder所能提供的更多的选项,我简单地使用initState();调用了块提供程序并添加了事件。

class _ExampleScreenState extends State<ExampleScreen> {
    

  @override
  void initState() {
    super.initState();
    BlocProvider.of<OneBloc>(context)
        .add(FetchData);
  }

它之所以有效,是因为块已经从根小部件提供。

2fjabf4q

2fjabf4q3#

简而言之:
1.使用BlocProvider,在创建过程中调用它。

BlocProvider(create: (context) => ExampleBloc()..add(Fetch()))

1.使用BlocState,将其用作

class _ExampleScreenStateState extends State<ExampleScreenState> {
   ExampleBloc _exampleBloc;

   @override
  void initState() {
  super.initState();
  _exampleBloc = ExampleBloc()..add(Fetch());
}

@override
void dispose() {
  super.dispose();
  _exampleBloc.close();

}

相关问题