Flutter: Widget derlemesinde çalıştırma yöntemi tamamlandı


125

Bir Widget oluşturmayı / yüklemeyi bitirdiğinde işlevleri çalıştırabilmek istiyorum, ancak nasıl yapılacağından emin değilim. Mevcut kullanım durumum, bir kullanıcının kimlik doğrulamasının yapılıp yapılmadığını kontrol etmek ve değilse, bir oturum açma görünümüne yönlendirmektir. Daha önce kontrol etmek ve giriş görünümünü veya ana görünümü itmek istemiyorum, ana görünüm yüklendikten sonra gerçekleşmesi gerekiyor. Bunu yapmak için kullanabileceğim bir şey var mı?


Giriş işlemini başlatmak istemeniz olası değildir build. Build herhangi bir zamanda birden çok kez çağrılabilir.
Günter Zöchbauer

Yanıtlar:


182

Kullanabilirsin

https://github.com/slightfoot/flutter_after_layout

düzen tamamlandıktan sonra bir işlevi yalnızca bir kez çalıştırır. Ya da uygulamasına bakın ve kodunuza ekleyin :-)

Hangisi temelde

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

Teşekkürler @thomas, ans benim için çok yararlı. Bunun üzerinde iki gün önce çalışıyorum ve şimdi onlar ve sizin anlarınızı okuduktan sonra. tekrar çok teşekkür ederim çok iyi iş çıkardınız
Ravindra Bhanderi

6
@ Anmol.majhail cevabına bakın: WidgetsBinding.instance.addPostFrameCallback((_) => yourFunciton(context));artık çalışmıyor
Pablo Insua

Merhaba @Thomas, benim için çalışmıyor. yine de boş istisna oluyor. Herhangi bir fikir ?
zukijuki

1
@anunixercoder: kullanım durumunuza bağlıdır. Bazen initState, örneğin, dışında başka bir yerde aramalısınız . içinde build.
Giraldi

2
Çalışması için yöntem setStateiçinde çağırmalısınızyourFunction
Pars

89

GÜNCELLEME: Flutter v1.8.4

Bahsedilen her iki kod da şu anda çalışıyor:

Çalışma:

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

Çalışma

import 'package:flutter/scheduler.dart';

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

1
İkincisi artık çalışmıyor. NoSuchMethodError (NoSuchMethodError: The method 'addPostFrameCallback' was called on null. Receiver: null
Oliver Dixon

1
@EliaWeiss - Kullanım durumunuza bağlıdır - Bu, oluşturulduktan sonra Widget'larda bir işlevi çağırmanın bir yoludur. tipik kullanım init () 'de olacak
anmol.majhail

20

3 olası yol vardır:

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

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

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

Gelince context, Scaffold.of(context)tüm widget'larım oluşturulduktan sonra kullanmak için ona ihtiyacım vardı.

Ama alçakgönüllü görüşüme göre, bunu yapmanın en iyi yolu şudur:

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

13

Flutter 1.2 - dart 2.2

Resmi kurallar ve ile göre kaynaklar da emin olmak istiyorsanız Düzeninize son karesi Örneğin yazabilirsiniz drawned edildi:

import 'package:flutter/scheduler.dart';

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

Benim için bu işe yaramadı, çünkü initState () zamanında SchedulerPhase.idle değerine sahip schedulerPhase'i aldım ... aslında işe yarayan şey, build () içindeki bu çeki eklemekti
Alessio

11

ReactNative'in componentDidMounteşdeğerini arıyorsanız , Flutter'da var. O kadar basit değil ama aynı şekilde çalışıyor. Flutter'da, Widgets olaylarını doğrudan işlemez. Bunun yerine State, bunu yapmak için nesnelerini kullanırlar.

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.initStateekran düzeni oluşturma tamamlandığında hemen çağrılacaktır. Ve hata ayıklama modundaysanız, açıkça bunu yapmak için zamana gelene kadar çalışırken yeniden yüklemede bile bir daha asla çağrılmayacaktır.


Örneğimden, nesnesini bir a gibi StatefulWidgetişlemek için sınıfı kullanabilirsiniz, ancak kesinlikle önermiyorum. Henüz herhangi bir sorun bulamadım ama lütfen önce nesnenin içindeki her şeyi uygulamaya çalışınStateStatelessWidgetState
jerinho.com

2
flutter.dev/docs/cookbook/networking/fetch-data Google, initState () üzerinde veri getirmeyi çağırmanızı önerir. Dolayısıyla bu çözümle ilgili bir sorun yok, aslında kabul edilen cevap bu olmalı.
Geliştirici

React Native'de veri getirme, componentWillMountdüzen oluşturmadan hemen önce yapılabilir. Flutter daha basit bir çözüm sağlar. initStatedoğru bir şekilde nasıl yapılacağını
bilirsek

1
componentWillMount yakında kullanımdan kaldırılacak. Bu nedenle getirme, bileşen monte edildikten ve oluşturulduktan sonra yapılacaktır.
Geliştirici

8

Flutter sürüm 1.14.6, Dart sürüm 28'de.

Aşağıda benim için işe yarayan şey var, sadece inşa yönteminden sonra olmasını istediğiniz her şeyi ayrı bir yöntem veya işlevde bir araya getirmeniz yeterlidir.

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

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

}

3

SchedulerBinding'i deneyin,

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

1

Bunu yapmanın en iyi yolları,

1. WidgetsBinding

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

2. WidgetsBinding

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

İçeride çağrılabilir initState, her ikisi de oluşturma ile tamamlandıktan sonra yalnızca bir kez çağrılır.

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

Yukarıdaki kodların her ikisi de benzer bağlama çerçevesini kullandığından aynı şekilde çalışacaktır. Fark için aşağıdaki bağlantıyı bulun.

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


0

Bunu yalnızca bir kez yapmak istiyorsanız, bunu yapın çünkü çerçeve, initState()oluşturduğu her State nesnesi için yöntemi tam olarak bir kez çağıracaktır .

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

Bunu tekrar tekrar yapmak isterseniz, arkada olduğu gibi veya bir sonraki ekrana vb. didChangeDependencies()Gitmek istiyorsanız, bunu yapın çünkü bu Durum nesnesinin bir bağımlılığı değiştiğinde Çağırılır.

Önceki çağrı Örneğin, buildbaşvurulan bir InheritedWidgetsonraki değişti, çerçeve değişikliği ile ilgili bu nesneyi bildirmek için bu yöntemi çağırır.

Bu yöntem hemen ardından da çağrılır initState. BuildContext.dependOnInheritedWidgetOfExactTypeBu yöntemden aramak güvenlidir .

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

Bu, Geri Arama işlevinizdir

executeAfterBuildComplete([BuildContext context]){
    print("Build Process Complete");
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.