Bloc olayları Widget'ın dışında nasıl gönderilir?

Aug 18 2020

Bloc mimarisinde yeniyim ve son zamanlarda bazı eğitimler izledim. StatelessWidget olan sayfam var ve içinde Bloc'u arayüzüm içinde başlatmak için BlocProvider kullanıyorum. Durum değişikliklerine göre farklı widget'lar döndürecektir.

Ancak öğreticilerde bile yalnızca diğer Widget'lardan (örneğin Düğmeye basarak) olayları gönderdiler. Ama benim durumumda Bloc Event'te bulunan Widget'ın dışında init API çağrısını çağırmam gerekiyor.

Eğer başka bir Widget'ın içindeysem arayabilirim BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());ama onu main () içinde arayamıyorum çünkü içerik Widget'tan değil.

Kod:

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,
                      ),
                      width: MediaQuery.of(context).size.width,
                      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,
                        );
                      }
                    },
                  ),
                ],
              ),
            ],
          ),
        )));
  }
}

Yanıtlar

1 Kherel Aug 18 2020 at 15:30

Bloğu elde etmek için başka bir yol kullanmanız gerekiyor.

BlocProvider.of(context)Providerkaputun altında kullanır . Sağlayıcı , sarmalayan bir flutter paketidir InheritedWidget. InheritedWidget , verileri bağlam yoluyla pencere öğesi ağacından geçiren flutter widget'tır.

Yani başka bir yola ihtiyacınız var. Örneğin get_it kitaplığını kullanabilirsiniz . Dart uygulaması Service Locator.

Widget'ın dışındaki bloğun basit bir örneği

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'));
    }
  }
}

Bloğunuzu get_it'e kaydedin. Ve bundan sonra onu alabilir ve bağlam olmadan kullanabilirsiniz.