Flutter: Unhandled Exception: ServicesBinding.defaultBinaryMessenger był dostępny przed zainicjowaniem powiązania

134

Jakieś rozwiązanie tego problemu?

Ślad stosu:

[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
#0      defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:73:7)
#1      defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:86:4)
#2      MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:140:62)
#3      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:314:35)
<asynchronous suspension>
#4      MethodChannel.invokeMapMethod (package:f<>
Sopheadavid Sopheap
źródło
umieść tę linię jako pierwszą instrukcję w main () - WidgetsFlutterBinding.ensureInitialized ();
Vijay Ram

Odpowiedzi:

312

Ten problem pojawia się po ulepszeniu Fluttera. Powodem tego jest to, że czekasz na jakieś dane lub uruchamiasz asyncfunkcję w środku main().

Inicjowałem się ScopedModelwewnątrz main()i wewnątrz, czekając na jakieś dane.

Jest bardzo mała poprawka. Po prostu wbiegnij do WidgetsFlutterBinding.ensureInitialized()środka void main(), zanim to zrobisz runApp(). Działa jak marzenie!!

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(Delta(
    model: ProductDataModel(),
  ));
}
Debasmita Sarkar
źródło
17
upewnij się, że WidgetFlutterBinding.ensureInitialized () jest pierwszym wierszem funkcji main (). a następnie postępuj jak zwykle
Avnish kumar
10
Jaki jest potencjalny negatywny wpływ tego? Czy wszystkie aplikacje flutter powinny mieć tę linię na początku main()metody?
user482594
3
Jeśli używasz metody async w main (), musisz to dodać
Debasmita Sarkar
2
nie działa w przypadku przerwy w wersji 1.14.4 / 1.14.6 na var databasesPath = await getDatabasesPath ();
Ares91
70

Zwykle dzieje się tak, jeśli czekasz na main()metodę. Tak więc rozwiązaniem byłoby:

void main() {
  // add this, and it should be the first line in main method
  WidgetsFlutterBinding.ensureInitialized(); 

  // rest of your app code
  runApp(
    MaterialApp(...),
  );
}
CopsOnRoad
źródło
1
nie działa - przerwy przy dołączaniu (await getDatabasesPath (), 'mydb.db'),
live-love
25

Nie jestem pewien, czy mam poprawną odpowiedź, ale mam ten sam błąd po ostatniej aktualizacji trzepotania i udało mi się go uruchomić, więc dzielę się swoimi odkryciami.

Wygląda na to, że błąd może być spowodowany niedawną istotną zmianą: https://groups.google.com/forum/#!msg/flutter-announce/sHAL2fBtJ1Y/mGjrKH3dEwAJ .

W rezultacie musimy ręcznie zmienić kod w następujący sposób:

  • Jeśli uruchamiasz aplikację i potrzebujesz uzyskać dostęp do binarnego komunikatora przed runApp()wywołaniem (na przykład podczas inicjalizacji wtyczki), musisz jawnie wywołać WidgetsFlutterBinding.ensureInitialized()pierwszy.
  • Jeśli uruchamiasz test, możesz wywołać TestWidgetsFlutterBinding.ensureInitialized()pierwszą linię w main()metodzie testu, aby zainicjować powiązanie.

Alternatywnie, jeśli jesteś nowicjuszem, takim jak ja, i masz trudności ze zrozumieniem powyższych i # 38464 , możesz tymczasowo uniknąć tego problemu, przełączając się na kanał beta. Po prostu uruchom "flutter channel beta". Przełomowa zmiana nie jest jeszcze w wersji beta, więc po przejściu na kanał beta nie pojawi się ten błąd przynajmniej na razie.

Mars
źródło
Dziękuję brachu, teraz właśnie użyłem wersji beta, aby uniknąć błędów!
Sopheadavid Sopheap
11

po prostu dodaj tę linię w main.dart

WidgetsFlutterBinding.ensureInitialized(); 

wygląda na to, że twój kod

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  return runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider.value(
        value: AppState(),
      )
    ],
    child: MyApp(),
  ));
}
Saad Ahmed
źródło
2

w moim przypadku podczas korzystania z orientacji,

przed rozwiązaniem:

void main() {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then((_).{
runApp(MyApp());
});
}

rozwiązane użycie:

void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
  .then((_) {
runApp(MyApp());
});
}

Chodzi o to, aby dodać WidgetsFlutterBinding.ensureInitialized () w pierwszym wierszu klasy głównej

arjava
źródło
2

Możesz napotkać to, jeśli próbujesz wykonać natywny kod wtyczki w izolacji. Dokumentacja isolate_handler tutaj dobrze to wyjaśnia:

Wtyczki używają mechanizmu zwanego kanałem platformy do komunikacji między Dart a natywnymi stronami, mechanizm przekazywania wiadomości przy użyciu typu MethodChannel. Ten mechanizm zależy od działania elementów bazowego silnika interfejsu użytkownika.

Problem polega na tym, że izolaty zapewnią wzrost wydajności tylko w przypadku kosztownego obliczeniowo kodu do rzutek. Kod platformy wtyczki ponownie użyje wątku głównego (UI).

Wywołanie WidgetsFlutterBinding.ensureInitializedwewnątrz izolacji również zakończy się niepowodzeniem z powodu braku bazowego silnika interfejsu użytkownika w izolacie.

sjsam
źródło
1

Zanim miałem wersję v1.12.13+hotfix.5, przełączyłem się na wersję v1.14.4i zadziałało.

Błąd mówi, że powinieneś dodać WidgetsFlutterBinding.ensureInitialized();, ale ponieważ to nie zadziałało dla mnie, przełączyłem się na inną wersję. Jedną rzeczą, o której należy pamiętać, jest to, że nadal musisz dodać WidgetsFlutterBinding.ensureInitialized();jako pierwszą linię w swoim main!

hanslissi
źródło
1

Rozwiązanie: Wywołaj WidgetsFlutterBinding.ensureInitialized(); przed wywołaniem funkcji asynchronicznych.


void main() async {
  WidgetsFlutterBinding.ensureInitialized();   //  ADD THIS BEFORE YOUR ASYNC FUNCTION CALL.
  await Firestore.instance.settings(...);      //  NOW YOU CAN CALL ASYNC FUNCTION.   
  ...
  runApp(
    ...
  )
JesusIniesta
źródło