Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A AndroidPullToRefreshController was used after being disposed #2104

Open
2 tasks done
maxmitz opened this issue Apr 15, 2024 · 4 comments
Open
2 tasks done

A AndroidPullToRefreshController was used after being disposed #2104

maxmitz opened this issue Apr 15, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@maxmitz
Copy link
Contributor

maxmitz commented Apr 15, 2024

  • I have read the Getting Started section
  • I have already searched for the same problem

Lorenzo Pichilli Thanks for maintaining the InAppWebView!

Environment

Technology Version
Flutter version 3.19.3
Plugin version 6.0.0
Android version 33.0.1
iOS version 17.4.1
macOS version -
Xcode version 15.0
Google Chrome version -

Device information: reproducible on emulators and on real devices

Description

I am not 100% sure if this is a bug or intended. I think it is a bug.

When I reload the web view fast multiple times. The AndroidInAppWebViewWidget wants to dispose the AndroidPullToRefreshController but the controller was already disposed.

For the given example, there should be a timeout or something similar on the floatingActionButton but in general, I think that this should be the responsibility of the plugin to check if the pulltorefreshcontroller was already disposed, or do I oversee something?

#1997 (comment)

In this comment Lorenzo Pichilli stated that the InAppWebViewController is null if it was disposed. Shouldn't the same apply to the RefreshController?

From in_app_webview.dart
params.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive);

Expected behavior:

The plugin should check if PulltoRefreshController was disposed.

Current behavior:

The implementing developer has to check if the PullToRefreshController has been disposed

Steps to reproduce

  1. Run code
  2. Click fast multiple times on the floatingActionButton.
  3. Error occurs.

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@OverRide
Widget build(BuildContext context) {
return const MaterialApp(home: MyHomePage());
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});

@OverRide
State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
UniqueKey key = UniqueKey();

@OverRide
Widget build(BuildContext context) {
final pullToRefreshController = PullToRefreshController();

return Scaffold(
  body: Column(
    children: [
      Expanded(
        child: InAppWebView(
          key: key,
          pullToRefreshController: pullToRefreshController,
          onLoadStop: (_, __) {
            pullToRefreshController.endRefreshing();
          },
          initialUrlRequest:
              URLRequest(url: WebUri.uri(Uri.parse("https://flutter.dev"))),
        ),
      )
    ],
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {
      setState(() {
        key = UniqueKey();
      });
    },
    child: const Icon(Icons.add),
  ),
);

}
}

Images

Bildschirmfoto 2024-04-15 um 13 07 36

Stacktrace/Logcat

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
A AndroidPullToRefreshController was used after being disposed.
Once the AndroidPullToRefreshController has been disposed, it can no longer be used.

When the exception was thrown, this was the stack:
#0 ChannelController.debugAssertNotDisposed. (package:flutter_inappwebview_platform_interface/src/util.dart:595:9)
util.dart:595
#1 ChannelController.debugAssertNotDisposed (package:flutter_inappwebview_platform_interface/src/util.dart:602:6)
util.dart:602
#2 InternalChannelController.channel (package:flutter_inappwebview_platform_interface/src/util.dart:611:30)
util.dart:611
#3 InternalChannelController.disposeChannel (package:flutter_inappwebview_platform_interface/src/util.dart:641:7)
util.dart:641
#4 AndroidPullToRefreshController.dispose (package:flutter_inappwebview_android/src/pull_to_refresh/pull_to_refresh_controller.dart:152:5)
pull_to_refresh_controller.dart:152
#5 AndroidInAppWebViewWidget.dispose (package:flutter_inappwebview_android/src/in_app_webview/in_app_webview.dart:467:37)
in_app_webview.dart:467
#6 _InAppWebViewState.dispose (package:flutter_inappwebview/src/in_app_webview/in_app_webview.dart:673:21)
in_app_webview.dart:673
#7 StatefulElement.unmount (package:flutter/src/widgets/framework.dart:5689:11)
framework.dart:5689
#8 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2076:13)
framework.dart:2076

@maxmitz maxmitz added the bug Something isn't working label Apr 15, 2024
Copy link

👋 @maxmitz

NOTE: This comment is auto-generated.

Are you sure you have already searched for the same problem?

Some people open new issues but they didn't search for something similar or for the same issue. Please, search for it using the GitHub issue search box or on the official inappwebview.dev website, or, also, using Google, StackOverflow, etc. before posting a new one. You may already find an answer to your problem!

If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible. Please, make sure you have given me as much context as possible! Also, if you didn't already, post a code example that can replicate this issue.

In the meantime, you can already search for some possible solutions online! Because this plugin uses native WebView, you can search online for the same issue adding android WebView [MY ERROR HERE] or ios WKWebView [MY ERROR HERE] keywords.

Following these steps can save you, me, and other people a lot of time, thanks!

@Julied5
Copy link

Julied5 commented Apr 24, 2024

Is there any update on this ? I'm getting the same issue since 6.0.0 upgrade, does someone have a way to prevent this error ?

@2x2xplz
Copy link

2x2xplz commented May 10, 2024

Same issue. This appears to be a leftover debugging artifact that could be removed from the release version. If the developer manually disposes the webview and its controller, eventually the library internally calls its own dispose() method, which calls debugAssertNotDisposed(). This method throws an error below when the controller has already been disposed. Maybe the controller could be checked for disposal further up the stack rather than in this assert.

In the meantime, you can avoid this error by manually dispose()ing your webview, but NOT disposing the controller. But I think I'd rather dispose them both myself rather than just assume it will happen automatically.

  static bool debugAssertNotDisposed(ChannelController controller) {
    assert(() {
      if (controller.disposed) {
        throw FlutterError(
          'A ${controller.runtimeType} was used after being disposed.\n'
          'Once the ${controller.runtimeType} has been disposed, it '
          'can no longer be used.',
        );
      }
      return true;
    }());
    return true;
  }
E/flutter ( 4982): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: A AndroidInAppWebViewController was used after being disposed.
E/flutter ( 4982): Once the AndroidInAppWebViewController has been disposed, it can no longer be used.
E/flutter ( 4982): #0      ChannelController.debugAssertNotDisposed.<anonymous closure> (package:flutter_inappwebview_platform_interface/src/util.dart:595:9)
E/flutter ( 4982): #1      ChannelController.debugAssertNotDisposed (package:flutter_inappwebview_platform_interface/src/util.dart:602:6)
E/flutter ( 4982): #2      InternalChannelController.channel (package:flutter_inappwebview_platform_interface/src/util.dart:611:30)
E/flutter ( 4982): #3      InternalChannelController.disposeChannel (package:flutter_inappwebview_platform_interface/src/util.dart:641:7)
E/flutter ( 4982): #4      AndroidInAppWebViewController.dispose (package:flutter_inappwebview_android/src/in_app_webview/in_app_webview_controller.dart:2756:5)
E/flutter ( 4982): #5      AndroidHeadlessInAppWebView.dispose (package:flutter_inappwebview_android/src/in_app_webview/headless_in_app_webview.dart:427:25)

@Harishwarrior
Copy link

Same issue. This appears to be a leftover debugging artifact that could be removed from the release version. If the developer manually disposes the webview and its controller, eventually the library internally calls its own dispose() method, which calls debugAssertNotDisposed(). This method throws an error below when the controller has already been disposed. Maybe the controller could be checked for disposal further up the stack rather than in this assert.

In the meantime, you can avoid this error by manually dispose()ing your webview, but NOT disposing the controller. But I think I'd rather dispose them both myself rather than just assume it will happen automatically.

  static bool debugAssertNotDisposed(ChannelController controller) {
    assert(() {
      if (controller.disposed) {
        throw FlutterError(
          'A ${controller.runtimeType} was used after being disposed.\n'
          'Once the ${controller.runtimeType} has been disposed, it '
          'can no longer be used.',
        );
      }
      return true;
    }());
    return true;
  }
E/flutter ( 4982): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: A AndroidInAppWebViewController was used after being disposed.
E/flutter ( 4982): Once the AndroidInAppWebViewController has been disposed, it can no longer be used.
E/flutter ( 4982): #0      ChannelController.debugAssertNotDisposed.<anonymous closure> (package:flutter_inappwebview_platform_interface/src/util.dart:595:9)
E/flutter ( 4982): #1      ChannelController.debugAssertNotDisposed (package:flutter_inappwebview_platform_interface/src/util.dart:602:6)
E/flutter ( 4982): #2      InternalChannelController.channel (package:flutter_inappwebview_platform_interface/src/util.dart:611:30)
E/flutter ( 4982): #3      InternalChannelController.disposeChannel (package:flutter_inappwebview_platform_interface/src/util.dart:641:7)
E/flutter ( 4982): #4      AndroidInAppWebViewController.dispose (package:flutter_inappwebview_android/src/in_app_webview/in_app_webview_controller.dart:2756:5)
E/flutter ( 4982): #5      AndroidHeadlessInAppWebView.dispose (package:flutter_inappwebview_android/src/in_app_webview/headless_in_app_webview.dart:427:25)

How can you dispose the webview instead of the controller?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants