स्पंदन: विजेट पर रन विधि पूर्ण निर्माण


134

एक बार जब कोई विजेट निर्माण / लोडिंग समाप्त कर लेता है, तो मैं फ़ंक्शंस को चलाने में सक्षम होना चाहता हूं, लेकिन मैं अनिश्चित हूं कि कैसे। मेरा वर्तमान उपयोग मामला यह जांचने के लिए है कि क्या उपयोगकर्ता प्रमाणित है और यदि नहीं, तो एक लॉगिन दृश्य पर रीडायरेक्ट। मैं पहले नहीं देखना चाहता हूं कि लॉगिन दृश्य या मुख्य दृश्य को या तो धकेल दें, मुख्य दृश्य लोड होने के बाद ऐसा होना चाहिए। क्या ऐसा करने के लिए मैं कुछ भी कर सकता हूं?


यह संभावना नहीं है कि आप लॉगिन प्रक्रिया शुरू करना चाहते हैं build। बिल्ड को कई बार किसी भी समय कॉल किया जा सकता है।
गुंटर ज़ोचबॉउर

जवाबों:


195

आप उपयोग कर सकते हैं

https://github.com/slightfoot/flutter_after_layout

जो लेआउट पूरा होने के एक समय बाद ही किसी फंक्शन को अंजाम देता है। या बस इसके कार्यान्वयन को देखें और इसे अपने कोड में जोड़ें :-)

जो मूल रूप से है

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }

धन्यवाद @thomas आपका ans मेरे लिए बहुत मददगार है। मैं इस पर दो दिन से पहले और अब वे और आपके ans पढ़ने के बाद काम करते हैं। फिर से शुक्रिया बहुत अच्छा काम
रविन्द्र भंडारी

8
देखें @ anmol.majhail उत्तर: WidgetsBinding.instance.addPostFrameCallback((_) => yourFunciton(context));अब काम नहीं कर रहा है
पाब्लो इनसु

हाय @ थोमस, यह मेरे लिए काम नहीं कर रहा है। अभी भी अशक्त अपवाद मिलता है। कोई उपाय ?
zukijuki

1
@anunixercoder: यह आपके उपयोग के मामले पर निर्भर करता है। समय पर, आपको इसे अन्य की तरह कॉल करना चाहिए initState, जैसे। में है build
गिरलड़ी

2
आपको इसे काम करने के लिए विधि के setStateभीतर कॉल करना चाहिएyourFunction
पारस

92

अद्यतन: स्पंदन v1.8.4

दोनों उल्लिखित कोड अब काम कर रहे हैं:

काम कर रहे:

WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));

काम कर रहे

import 'package:flutter/scheduler.dart';

SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));

1
दूसरा अब कोई काम नहीं करता। NoSuchMethodError (NoSuchMethodError: The method 'addPostFrameCallback' was called on null. Receiver: null
ओलिवर डिक्सन

1
@EliaWeiss - यह आपके उपयोग के मामले पर निर्भर करता है - यह निर्माण के बाद विजेट्स पर एक फ़ंक्शन को कॉल करने का एक तरीका है। विशिष्ट उपयोग init ()
anmol.majhail

21

3 संभावित तरीके हैं:

1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));

2) Future.delayed(Duration.zero, () => yourFunc(context));

3) Timer.run(() => yourFunc(context));

के रूप में context, मैं Scaffold.of(context)अपने सभी विगेट्स प्रदान किए जाने के बाद इसे उपयोग के लिए आवश्यक था।

लेकिन मेरी विनम्र राय में, यह करने का सबसे अच्छा तरीका यह है:

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
  await yourFunc();
  runApp( MyApp() );
}

14

स्पंदन 1.2 - डार्ट 2.2

आधिकारिक दिशानिर्देशों और स्रोतों के अनुसार यदि आप निश्चित होना चाहते हैं कि आपके लेआउट का अंतिम फ्रेम भी खींचा गया है तो आप उदाहरण के लिए लिख सकते हैं:

import 'package:flutter/scheduler.dart';

void initState() {
   super.initState();
   if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
        SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
   }
}

मेरे लिए यह काम नहीं किया, क्योंकि initState () समय पर मुझे शेड्यूलरपेज़ मिलता है SchedulerPhase.idle वैल्यू के साथ ... जो वास्तव में काम करता है वह बिल्ड के भीतर उस चेक को जोड़ने के लिए था ()
Alessio

11

यदि आप ReactNative के componentDidMountसमकक्ष की तलाश कर रहे हैं, तो Flutter के पास है। यह इतना आसान नहीं है, लेकिन यह उसी तरह काम कर रहा है। स्पंदन में, Widgetसीधे अपनी घटनाओं को नहीं संभालते हैं। इसके बजाय वे Stateऐसा करने के लिए अपनी वस्तु का उपयोग करते हैं।

class MyWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => MyState(this);

  Widget build(BuildContext context){...} //build layout here

  void onLoad(BuildContext context){...} //callback when layout build done
}

class MyState extends State<MyWidget>{

  MyWidget widget;

  MyState(this.widget);

  @override
  Widget build(BuildContext context) => widget.build(context);

  @override
  void initState() => widget.onLoad(context);
}

State.initStateएक बार स्क्रीन पर लेआउट को रेंडर करने के बाद तुरंत कॉल किया जाएगा। और फिर से गर्म पुनः लोड पर भी कभी नहीं बुलाया जाएगा यदि आप डिबग मोड में हैं, जब तक कि स्पष्ट रूप से ऐसा करने के लिए समय पर नहीं पहुंचता।


मेरे उदाहरण से, आप StatefulWidgetकक्षा का उपयोग कर सकते हैं यह Stateवस्तु की तरह संभालने के लिए है, StatelessWidgetलेकिन मैं इसकी अनुशंसा नहीं करता। मुझे अभी तक कोई मुद्दा नहीं मिला है, लेकिन कृपया Stateपहले वस्तु के अंदर सब कुछ लागू करने का प्रयास करें
jerinho.com

2
flutter.dev/docs/cookbook/networking/fetch-data Google initState () पर डेटा प्राप्त करने के लिए कॉल करने की अनुशंसा करता है। इसलिए इस समाधान के साथ कोई समस्या नहीं है, वास्तव में यह स्वीकृत उत्तर होना चाहिए।
डेवलपर

React में Native data fetch, componentWillMountलेआउट रेंडरिंग से ठीक पहले किया जा सकता है । स्पंदन सरल समाधान प्रदान करता है। initStateयदि हम जानते हैं कि इसे ठीक से कैसे किया जाए, तो डेटा प्राप्त करने और दिए गए लेआउट पर दोनों के लिए पर्याप्त है
jerinho.com

1
ComponentsWillMount जल्द ही हटा दिया जाएगा। इसलिए घटक को आरोहित करने और निर्माण करने के बाद लाने का काम किया जाएगा।
डेवलपर

10

स्पंदन संस्करण 1.14.6 में, डार्ट संस्करण 28।

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

@override
void initState() {
super.initState();
print('hello girl');

WidgetsBinding.instance
    .addPostFrameCallback((_) => afterLayoutWidgetBuild());

}

5

इसे करने के सर्वोत्तम तरीके,

1. विजेटबाइंडिंग

WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });

2. विजेटबाइंडिंग

SchedulerBinding.instance.addPostFrameCallback((_) {
  print("SchedulerBinding");
});

इसे अंदर कहा जा सकता है initState, दोनों को केवल एक बार बनाया जा सकता है जब बिल्ड विजेट्स को रेंडरिंग के साथ किया जाता है।

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("initState");
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });
    SchedulerBinding.instance.addPostFrameCallback((_) {
      print("SchedulerBinding");
    });
  }

उपरोक्त दोनों कोड समान कार्य करेंगे क्योंकि दोनों समान बाइंडिंग फ्रेमवर्क का उपयोग करते हैं। अंतर के लिए नीचे दिए गए लिंक को ढूंढें।

https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f


3

शेड्यूलर बाइंडिंग का प्रयास करें,

 SchedulerBinding.instance
                .addPostFrameCallback((_) => setState(() {
              isDataFetched = true;
            }));

0

यदि आप इसे केवल एक बार करना चाहते हैं, तो इसे करें क्योंकि फ्रेमवर्क initState()प्रत्येक राज्य ऑब्जेक्ट के लिए एक बार विधि को कॉल करेगा ।

 @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

यदि आप बार-बार ऐसा करना चाहते हैं तो बैक पर जाएं या अगली स्क्रीन पर नेविगेट करें और आदि ..., तब करें क्योंकि didChangeDependencies()जब कॉल किया जाता है तो इस स्टेट ऑब्जेक्ट की निर्भरता बदल जाती है।

उदाहरण के लिए, यदि पिछले कॉल को buildसंदर्भित किया जाता है InheritedWidgetजो बाद में बदल गया है, तो फ्रेमवर्क इस पद्धति को कॉल के बारे में सूचित करने के लिए बदल देगा।

इस विधि को तुरंत बाद भी कहा जाता है initStateBuildContext.dependOnInheritedWidgetOfExactTypeइस विधि से कॉल करना सुरक्षित है ।

 @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

यह आपका कॉलबैक फ़ंक्शन है

executeAfterBuildComplete([BuildContext context]){
    print("Build Process Complete");
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.