Home > Software engineering >  Understanding Future and Completer in Flutter.... How to use the controller to load a new url from a
Understanding Future and Completer in Flutter.... How to use the controller to load a new url from a

Time:11-18

I cannot load a new URL in flutter Webview... I have issues using then and Future in flutter Webview Controller...

In a flutter Webview, I would like to load the initialUrl, then programmatically retrieve some information from that web page... All works well so far... But then I want the Webview to automatically load another webpage... but I am not sure how to use the controller and the Completer to do that

Snippet:

WebView(
  initialUrl: 'https://flutter.dev',
  onWebViewCreated: (WebViewController webViewController) {
    _controller.complete(webViewController);
    },
  onPageFinished: (String url) async{
    if (url == 'https://flutter.dev') {
      // *** I retrieve some data, then I want to navigate ***
      _controller!.loadUrl('https://google.com'); // *** ERROR HERE ***
    }
  },
)

I tried using the controller directly,

_controller!.loadUrl('https://google.com');

it works if I don't use a Completer and instead I just assign the controller

_controller = webViewController;

but does not seem a recommended option:

I found other examples using a FutureBuilder, but I am not trying to build anything

Here is the full code, in case useful:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';

void main() {
  runApp(
    const MaterialApp(
      home: WebViewApp(),
    ),
  );
}

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

  @override
  State<WebViewApp> createState() => _WebViewAppState();
}

class _WebViewAppState extends State<WebViewApp> {
  final Completer<WebViewController> _controller = Completer<WebViewController>();
  
  @override Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter WebView'),),
      body: WebView(
        initialUrl: 'https://flutter.dev',
        onWebViewCreated: (WebViewController webViewController) {
          _controller.complete(webViewController);
          },
        onPageFinished: (String url) async{
          if (url == 'https://flutter.dev') {
            // *** I retrieve some data, then I want to navigate ***
            _controller!.loadUrl('https://google.com'); // *** ERROR HERE ***
          }
        },
      ),
    );
  }
}

CodePudding user response:

for the subject of how to use completer in that case!

Replace onPageFinished callback with the following snippet and read the comments carefully

  onPageFinished: (String url) async{
              // add the missing '/' at the end of the url since the url string is 'https://flutter.dev/' 
              // NOT 'https://flutter.dev'
              if (url == 'https://flutter.dev/') {
                // *** I retrieve some data, then I want to navigate ***
                final wvController = await _controller.future;
                await wvController.loadUrl('https://google.com');
                // ***
                // No More ERROR
                // HERE ***)
              }
            },

CodePudding user response:

The best way to do this is to use iterators and controllers. No need to mess with the index. After calling the moveNext() function, the URL in the iterator is updated. You can also open a new URL with the loadUrl() function of the controller.

import 'dart:io';

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

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

  @override
  State<SamplePage> createState() => _SamplePageState();
}

class _SamplePageState extends State<SamplePage> {
  late WebViewController _webViewController;
  Iterable<String> urlStrings = [
    'https://www.google.com/',
    'https://www.yahoo.com/',
    'https://www.bing.com/',
    'https://flutter.dev/',
    'https://altavista.com/'
  ];
  late Iterator<String> urlIterator;

  @override
  void initState() {
    super.initState();
    // init url iterator.
    urlIterator = urlStrings.iterator;
    urlIterator.moveNext();

    // Enable virtual display.
    if (Platform.isAndroid) WebView.platform = AndroidWebView();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: WebView(
        onWebViewCreated: (controller) => setState(() => _webViewController = controller),
        initialUrl: urlIterator.current,
        onPageFinished: (url) {
          urlIterator.moveNext();
          _webViewController.loadUrl(urlIterator.current);
        },
      ),
    );
  }
}
  • Related