विजेट के बाहर ब्लॉक घटनाओं को कैसे भेजें?

Aug 18 2020

मैं ब्लाक आर्किटेक्चर के लिए नया हूं और मैंने हाल ही में कुछ ट्यूटोरियल देखे हैं। मेरे पास पेज है जो स्टेटलेसविजेट है और अंदर मैं अपने यूआई के अंदर ब्लाक को इनिशियलाइज़ करने के लिए ब्लाकप्रोवाइडर का उपयोग कर रहा हूं। यह राज्य परिवर्तनों के आधार पर विभिन्न विजेट लौटाएगा।

लेकिन यहां तक ​​कि ट्यूटोरियल में भी वे अन्य विजेट्स (उदाहरण के लिए बटन दबाकर) से घटनाओं को भेजते हैं। लेकिन मेरी स्थिति में मुझे विजेट के बाहर init API कॉल करने की आवश्यकता है जो कि Bloc Event में है।

यदि मैं अन्य विजेट के अंदर हूं तो मैं कॉल कर सकता हूं BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());लेकिन मैं इसे मुख्य () में नहीं कह सकता क्योंकि संदर्भ विजेट से नहीं है।

कोड:

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,
                        );
                      }
                    },
                  ),
                ],
              ),
            ],
          ),
        )));
  }
}

जवाब

1 Kherel Aug 18 2020 at 15:30

ब्लॉक प्राप्त करने के लिए आपको दूसरे तरीके का उपयोग करने की आवश्यकता है।

BlocProvider.of(context)Providerहुड के तहत उपयोग करता है । प्रदाता एक स्पंदन पैकेज है, जो लपेटता है InheritedWidget। InheritedWidget स्पंदन विजेट है जो संदर्भ के माध्यम से विजेट ट्री के नीचे डेटा पास करता है।

तो आपको एक और तरीका चाहिए। उदाहरण के लिए आप 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 में पंजीकृत करें। और इसके बाद आप इसे प्राप्त कर सकते हैं और संदर्भ के बिना उपयोग किया जा सकता है।