fluttercommunity / flutter_webview_plugin

Community WebView Plugin - Allows Flutter to communicate with a native WebView.
https://pub.dev/packages/flutter_webview_plugin
Other
1.48k stars 929 forks source link

How to properly dispose webview upon hot restart? #845

Open brenzi opened 3 years ago

brenzi commented 3 years ago

When using this plugin, I get an error upon hot-restart:java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

[ +518 ms] E/MethodChannel#flutter_webview_plugin(18431): Failed to handle method call
[        ] E/MethodChannel#flutter_webview_plugin(18431): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.view.ViewGroup.addView(ViewGroup.java:4746)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.view.ViewGroup.addView(ViewGroup.java:4718)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at com.android.internal.policy.PhoneWindow.addContentView(PhoneWindow.java:468)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.app.Activity.addContentView(Activity.java:2702)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at com.flutter_webview_plugin.FlutterWebviewPlugin.openUrl(FlutterWebviewPlugin.java:143)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at com.flutter_webview_plugin.FlutterWebviewPlugin.onMethodCall(FlutterWebviewPlugin.java:53)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.os.MessageQueue.nativePollOnce(Native Method)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.os.MessageQueue.next(MessageQueue.java:325)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.os.Looper.loop(Looper.java:142)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at android.app.ActivityThread.main(ActivityThread.java:6541)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at java.lang.reflect.Method.invoke(Native Method)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
[        ] E/MethodChannel#flutter_webview_plugin(18431):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
[  +22 ms] E/flutter (18431): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: PlatformException(error, The specified child already has a parent. You must call removeView() on the child's parent first., null, java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
[        ] E/flutter (18431):   at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
[        ] E/flutter (18431):   at android.view.ViewGroup.addView(ViewGroup.java:4746)
[        ] E/flutter (18431):   at android.view.ViewGroup.addView(ViewGroup.java:4718)
[        ] E/flutter (18431):   at com.android.internal.policy.PhoneWindow.addContentView(PhoneWindow.java:468)
[        ] E/flutter (18431):   at android.app.Activity.addContentView(Activity.java:2702)
[        ] E/flutter (18431):   at com.flutter_webview_plugin.FlutterWebviewPlugin.openUrl(FlutterWebviewPlugin.java:143)
[        ] E/flutter (18431):   at com.flutter_webview_plugin.FlutterWebviewPlugin.onMethodCall(FlutterWebviewPlugin.java:53)
[        ] E/flutter (18431):   at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
[        ] E/flutter (18431):   at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
[        ] E/flutter (18431):   at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
[        ] E/flutter (18431):   at android.os.MessageQueue.nativePollOnce(Native Method)
[        ] E/flutter (18431):   at android.os.MessageQueue.next(MessageQueue.java:325)
[        ] E/flutter (18431):   at android.os.Looper.loop(Looper.java:142)
[        ] E/flutter (18431):   at android.app.ActivityThread.main(ActivityThread.java:6541)
[        ] E/flutter (18431):   at java.lang.reflect.Method.invoke(Native Method)
[        ] E/flutter (18431):   at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
[        ] E/flutter (18431):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
[        ] E/flutter (18431): )
[        ] E/flutter (18431): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:582:7)
[        ] E/flutter (18431): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:159:18)
[        ] E/flutter (18431): <asynchronous suspension>
[        ] E/flutter (18431): #2      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:332:12)
[        ] E/flutter (18431): #3      FlutterWebviewPlugin.launch (package:flutter_webview_plugin/src/base.dart:225:20)
[        ] E/flutter (18431): #4      Api.launchWebview (package:encointer_wallet/service/substrateApi/api.dart:110:10)
[        ] E/flutter (18431): #5      Api.init (package:encointer_wallet/service/substrateApi/api.dart:52:5)
[        ] E/flutter (18431): #6      _WalletAppState._initStore (package:encointer_wallet/app.dart:93:14)
[        ] E/flutter (18431): #7      _rootRunUnary (dart:async/zone.dart:1198:47)
[        ] E/flutter (18431): #8      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
[        ] E/flutter (18431): #9      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
[        ] E/flutter (18431): #10     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
[        ] E/flutter (18431): #11     Future._propagateToListeners (dart:async/future_impl.dart:725:32)
[        ] E/flutter (18431): #12     Future._completeWithValue (dart:async/future_impl.dart:529:5)
[        ] E/flutter (18431): #13     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:40:15)
[        ] E/flutter (18431): #14     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:311:13)
[        ] E/flutter (18431): #15     AsyncAction.run (package:mobx/src/api/async/async_action.dart)
[        ] E/flutter (18431): #16     _rootRunUnary (dart:async/zone.dart:1198:47)
[        ] E/flutter (18431): #17     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
[        ] E/flutter (18431): #18     _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
[        ] E/flutter (18431): #19     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
[        ] E/flutter (18431): #20     Future._propagateToListeners (dart:async/future_impl.dart:725:32)
[        ] E/flutter (18431): #21     Future._complete (dart:async/future_impl.dart:519:7)
[        ] E/flutter (18431): #22     new Future.microtask.<anonymous closure> (dart:async/future.dart:201:16)
[        ] E/flutter (18431): #23     _rootRun (dart:async/zone.dart:1182:47)
[        ] E/flutter (18431): #24     _CustomZone.run (dart:async/zone.dart:1093:19)
[        ] E/flutter (18431): #25     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
[        ] E/flutter (18431): #26     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
[        ] E/flutter (18431): #27     _rootRun (dart:async/zone.dart:1190:13)
[        ] E/flutter (18431): #28     _CustomZone.run (dart:async/zone.dart:1093:19)
[        ] E/flutter (18431): #29     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
[        ] E/flutter (18431): #30     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
[        ] E/flutter (18431): #31     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
[        ] E/flutter (18431): #32     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
[        ] E/flutter (18431): 

I believe the problem is that hot-restart doesn't call dispose() where we close the webview. https://github.com/encointer/encointer-wallet-flutter/blob/afc485de2ddf73b57d7b4956f418f3b1b44460f6/lib/app.dart#L121

Also deactivate() isn't called upon hot-restart

reassemble() is only called upon hot-reload (where we don't want to reload the webview), but not upon hot-restart

festelo commented 3 years ago

@fluttercommunity any help?

rednikisfun commented 10 months ago

Any update on this?

@brenzi did you find a workaround?