如何在Widget外部调度Bloc事件?

问题描述

我是Bloc架构的新手,最近我看了一些教程。我有一个页面是StatelessWidget,在里面,我正在使用BlocProvider初始化UI中的Bloc。它将根据状态变化返回不同的小部件。

但是,即使在教程中,他们也仅从其他Widget调度事件(例如,通过按Button)。但是在我的情况下,我需要在Bloc事件中的Widget外部调用init API调用

如果我在其他小部件中,则可以调用BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());,但是由于上下文不是来自小部件,所以不能在main()中调用它。

代码

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: firstTabElement(context),),appBar: EmptyAppBar(mainAppColor),);
  }

  BlocProvider<FirstTabBloc> firstTabElement(BuildContext context) {
    return BlocProvider(
        builder: (_) => sl<FirstTabBloc>(),child: Expanded(
            child: Container(
          height: MediaQuery.of(context).size.height,width: MediaQuery.of(context).size.width,child: Column(
            children: <Widget>[
              Stack(
                children: [
                  //Main Background
                  Column(children: <Widget>[
                    //Top part
                    Container(
                      constraints: BoxConstraints(
                        minHeight: 120,height: 300,decoration: new Boxdecoration(
                        gradient: LinearGradient(
                          begin: Alignment.topCenter,end: Alignment.bottomCenter,colors: ticketGradient,// Bottom part - white
                    Container(
                      color: basicWhite,]),//content above background
                  BlocBuilder<FirstTabBloc,FirstTabState>(
                    builder: (context,state) {
                      if (state is Uninitialized) {
                        return WalletWidget(
                          credit: formatPrice(0),currency: '€',);
                      } else if (state is Loading) {
                        return LoadingWidget();
                      } else if (state is Loaded) {
                        Wallet currWallet = state.profile.getWalletByClient(clientId);
                        return WalletWidget(
                          credit: formatPrice(currWallet.value),currency: formatCurrency(currWallet.currency),);
                      } else if (state is Error) {
                        return Messagedisplay(
                          message: state.message,);
                      }
                    },],)));
  }
}

解决方法

您需要使用另一种方式来获得集团。

BlocProvider.of(context)在后​​台使用ProviderProvider是一个颤振包,其中包装了InheritedWidgetInheritedWidget是颤动的小部件,可通过上下文将数据沿小部件树向下传递。

所以您需要另一种方式。例如,您可以使用get_it库。这是Service Locator的出色实现。

一个简单的示例,其中的小部件位于外部

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

final bloc = CounterBloc();

void main() {
  bloc.add(CounterEvent.increment);
  bloc.add(CounterEvent.increment);
  bloc.add(CounterEvent.increment);
  bloc.add(CounterEvent.increment);

  runApp(
    MyApp(),);
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',theme: ThemeData(
        primarySwatch: Colors.blue,),home: Scaffold(
        body: SafeArea(
          child: MyHomePage(),);
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) => bloc,child: CounterPage(),);
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter')),body: BlocBuilder<CounterBloc,int>(
        builder: (_,count) {
          return Center(
            child: Text('$count',style: Theme.of(context).textTheme.headline1),);
        },floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,mainAxisAlignment: MainAxisAlignment.end,children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 5.0),child: FloatingActionButton(
              child: const Icon(Icons.add),onPressed: () =>
                  context.bloc<CounterBloc>().add(CounterEvent.increment),Padding(
            padding: const EdgeInsets.symmetric(vertical: 5.0),child: FloatingActionButton(
              child: const Icon(Icons.remove),onPressed: () =>
                  context.bloc<CounterBloc>().add(CounterEvent.decrement),],);
  }
}

enum CounterEvent { increment,decrement }

class CounterBloc extends Bloc<CounterEvent,int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.decrement:
        yield state - 1;
        break;
      case CounterEvent.increment:
        yield state + 1;
        break;
      default:
        addError(Exception('unsupported event'));
    }
  }
}

在get_it中注册您的集团。然后,您可以在没有上下文的情况下使用它。

,

我想你需要知道 dispatch renamed to add

> There were core api changes introduced into 1.0.0:
bloc.state.listen -> bloc.listen
bloc.currentState -> bloc.state
bloc.dispatch -> bloc.add
bloc.dispose -> bloc.close

查看 https://link.medium.com/qnfMcEcW00 了解更多详情。 希望能帮到你?