'Flutter WebView only gets content the first time

I have a WebView where I parse the Site-content after the user presses a Button. If loading the site for the first time (initUrl), I get all the correct data. However if changing the sites within the browser, the site content is not loaded correctly. It feels like it only loads the first site correctly.

For example:

This is my initial Url:

'https://www.saturn.de/de/product/_apple-airpods-pro-in-ear-kopfhorer-bluetooth-weiss-2771284.html'

I parse it and I get all the correct images. However if going to another site and then back, I get other data. Why is this happening? I am lost here... What am I missing?

This is my WebView:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web View Example'),
      ),
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: WebView(
                initialUrl:
                    'https://www.saturn.de/de/product/_apple-airpods-pro-in-ear-kopfhorer-bluetooth-weiss-2771284.html',
                javascriptMode: JavascriptMode.unrestricted,
                onWebViewCreated: (WebViewController webViewController) {
                  _controller = webViewController;
                },
                javascriptChannels: <JavascriptChannel>{
                  _extractDataJSChannel(context),
                },
                onPageStarted: (String url) {
                  setState(() {
                    _isLoading = true;
                  });
                },
                onPageFinished: (String url) {
                  setState(() {
                    _imagesWithSize = [];

                    _currentUrl = url;
                    _isLoading = false;
                  });
                },
              ),
            ),
            Row(
              children: [
                IconButton(
                  onPressed: () {
                    _controller.goBack();
                  },
                  icon: Icon(
                    Icons.arrow_back,
                    size: 50,
                  ),
                ),
                Flexible(
                  child: RoundedCornersTextButton(
                    title: 'GET',
                    isEnabled: !_isLoading,
                    onTap: () async {
                      await _getData();
                    },
                  ),
                ),
                IconButton(
                  onPressed: () {
                    _controller.goForward();
                  },
                  icon: Icon(
                    Icons.arrow_forward,
                    size: 50,
                  ),
                ),
              ],
            ),
            SizedBox(
              height: 20,
            ),
            RoundedCornersTextButton(
              title: 'Google',
              isEnabled: !_isLoading,
              onTap: () async {
                await _controller.loadUrl('https://www.google.com');
              },
            ),
          ],
        ),
      ),
    );
  }

  JavascriptChannel _extractDataJSChannel(BuildContext context) {
    return JavascriptChannel(
      name: 'Flutter',
      onMessageReceived: (JavascriptMessage message) {
        String pageBody = message.message;
      },
    );
  }

As you can see I tried something with JavaScript but I can't get it to work.. Any help is appreciated!



Solution 1:[1]

Add the flutter_inappwebview to your pubspec.yaml like this:

dependencies:
  flutter_inappwebview: ^5.3.2

And add handler method in JavaScript side:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
    <h1>JavaScript Handler</h1>
    <button id='handleTest' onclick="window.flutter_inappwebview.callHandler('<yourJavaScriptMethod>');">Test</button>
</body>

Then use the InAppWebView instead of the WebView as below:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web View Example'),
      ),
      body: SafeArea(
        child: Column(
          children: [
            Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web View Example'),
      ),
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
          child: InAppWebView(
            initialOptions: InAppWebViewGroupOptions(
                android: AndroidInAppWebViewOptions(
                    useHybridComposition: true
                )
            ),
            onWebViewCreated: (InAppWebViewController controller) {
              _controller = controller
                ..addJavaScriptHandler(
                    handlerName: "<yourJavaScriptMethod>",
                    callback: (args) {
                      // handle
                      String pageBody = message.message;
                    });
            },
            onLoadStart: (InAppWebViewController controller, Uri url) {
              setState(() {
                _isLoading = true;
              });
            },
            onLoadStop: (InAppWebViewController controller, Uri url) {
              setState(() {
                _imagesWithSize = [];
                _currentUrl = url;
                _isLoading = false;
              });
            },
          ),
        ),
            Row(
              children: [
                IconButton(
                  onPressed: () {
                    _controller.goBack();
                  },
                  icon: Icon(
                    Icons.arrow_back,
                    size: 50,
                  ),
                ),
                Flexible(
                  child: RoundedCornersTextButton(
                    title: 'GET',
                    isEnabled: !_isLoading,
                    onTap: () async {
                      await _getData();
                    },
                  ),
                ),
                IconButton(
                  onPressed: () {
                    _controller.goForward();
                  },
                  icon: Icon(
                    Icons.arrow_forward,
                    size: 50,
                  ),
                ),
              ],
            ),
            SizedBox(
              height: 20,
            ),
            RoundedCornersTextButton(
              title: 'Google',
              isEnabled: !_isLoading,
              onTap: () async {
                await _controller.loadUrl('https://www.google.com');
              },
            ),
          ],
        ),
      ),
    );
  }
  

Solution 2:[2]

Try using webview_flutter: ^3.0.2 in pubspec.yaml file. I have modified your code and it's working fine.

            final Completer<WebViewController> _controller =
        Completer<WebViewController>();
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text('Flutter Web View Example'),
            ),
            body: SafeArea(
              child: Column(
                children: [
                  Expanded(
                    child: WebView(
                      initialUrl:
                      'https://www.saturn.de/de/product/_apple-airpods-pro-in-ear-kopfhorer-bluetooth-weiss-2771284.html',
                      javascriptMode: JavascriptMode.unrestricted,
                      onWebViewCreated: (WebViewController webViewController) {
                        _controller.complete(webViewController);
                      },
                      javascriptChannels: <JavascriptChannel>{
                        _extractDataJSChannel(context),
                      },
                      onPageStarted: (String url) {
      
                      },
                      onPageFinished: (String url) {
      
                      },
                    ),
                  ),
                  Row(
                    children: [
                      FutureBuilder<WebViewController>(
                          future: _controller.future,
                          builder: (BuildContext context,
                              AsyncSnapshot<WebViewController> controller) {
                            return  IconButton(
                              onPressed: () async {
                                await controller.data!.goBack();
                              },
                              icon: Icon(
                                Icons.arrow_back,
                                size: 50,
                              ),
                            );
                          }),
      
                      Flexible(
                        child: TextButton(
                          child: Text("get"),
      
                          onPressed: () async {
      
                          },
                        ),
                      ),
                      FutureBuilder<WebViewController>(
                          future: _controller.future,
                          builder: (BuildContext context,
                              AsyncSnapshot<WebViewController> controller) {
                            return  IconButton(
                              onPressed: () async {
                                await controller.data!.goForward();
                              },
                              icon: Icon(
                                Icons.arrow_forward,
                                size: 50,
                              ),
                            );
                          }),
                    ],
                  ),
                  SizedBox(
                    height: 20,
                  ),
                  FutureBuilder<WebViewController>(
                      future: _controller.future,
                      builder: (BuildContext context,
                          AsyncSnapshot<WebViewController> controller) {
                        return FloatingActionButton(
                          onPressed: () async {
                           await  controller.data!.loadUrl('https://www.google.com');
                          },
                          child: Text("Google"),
                        );
                      }),
      
                ],
              ),
            ),
          );
        }
      
        JavascriptChannel _extractDataJSChannel(BuildContext context) {
          return JavascriptChannel(
            name: 'Flutter',
            onMessageReceived: (JavascriptMessage message) {
              String pageBody = message.message;
            },
          );
        }
      }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Fakhriddin Abdullaev
Solution 2 user18520267