SoFunction
Updated on 2025-03-06

A simple guide to calling Flutter WebView and JS in detail

This article uses Flutter's official WebView plugin:/packages/webview_flutter

Calling WebView and JS is a must, but it seems that the articles you write now are not very clear. My simple guide is simply and roughly divided into two parts: JS calls Flutter and Flutter calls JS, refuse to be fancy and whistle, and ensure you can understand it at first glance and learn it.

Before you start, let’s briefly understand the APIs contained in the official WebView:

  • onWebViewCreated: Called after the WebView is created and will only be called once;
  • initialUrl: the url of the initial load;
  • javascriptMode: JS execution mode (whether JS execution is allowed);
  • javascriptChannels: Channel for JS and Flutter communication;
  • navigationDelegate: route delegate (can implement JS calling Flutter part by intercepting url here);
  • gestureRecognizers: gesture monitoring;
  • onPageFinished: Callback when the WebView is loaded.

JS calls Flutter

There are two ways to call Flutter in JS: send messages using javascriptChannels and intercept urls using routing delegate (navigationDelegate).

Method 1: Send message using javascriptChannels

The javascriptChannels parameter can be passed into a set of Channels. We can define a _alertJavascriptChannel variable. This channel is used to control the toast function of JS calling Flutter:

JavascriptChannel _alertJavascriptChannel(BuildContext context) {
 return JavascriptChannel(
  name: 'Toast',
  onMessageReceived: (JavascriptMessage message) {
   showToast();
  });
 }

WebView(
 avascriptChannels: <JavascriptChannel>[
  _alertJavascriptChannel(context),
 ].toSet(),
;

In the above code, we define an _alertJavascriptChannel variable and give it a name called Toast. This name attribute receives a string, which represents a protocol agreed by both parties when JS calls Flutter. JS uses this name to post the corresponding information to Flutter (the API is ('xxxxxx')). We write a simple button in the web page section, and then click to start the logic of JS calling Flutter:

&lt;button onclick="callFlutter()"&gt;callFlutter&lt;/button&gt;

function callFlutter(){
 ("JS calls Flutter");
}

onMessageReceived is the callback after Flutter receives the JS message. We can get the message content sent to us by JS. The JavascriptMessage class has only one message member variable of String type, so if you need to pass complex data, you can solve it by passing a json string.

Code focus: The name in JavascriptChannel should correspond to () in JS! !

Method 2: Use route delegate navigationDelegate to intercept url

The navigationDelegate callback is triggered every time the webpage routing address changes, so we can intercept specific urls to implement JS call Flutter.

Similarly, we write a simple button in the web page section, and then click to jump to the route "js://webview?arg1=111&args2=222". We can negotiate a scheme with the client, for example, in this example, js://webview, we can bring the parameters we want to pass on the query string:

&lt;button onclick="callFlutter()"&gt;callFlutter&lt;/button&gt;

function callFlutter(){
 /*The agreed url protocol is: js://webview?arg1=111&arg2=222*/
  = "js://webview?arg1=111&amp;args2=222";
}

On the Flutter side, we can intercept the route address that matches js://webviewscheme in the navigationDelegate callback:

navigationDelegate: (NavigationRequest request) {
   if (('js://webview')) {
    showToast('JS calls Flutter By navigationDelegate');
    print('blocking navigation to $request}');
    return ;
   }
   print('allowing navigation to $request');
   return ;
   },

We tell the WebView how to handle this route by returning different values:

  • : Block routing replacement;
  • : Allow routing replacement.

Flutter calls JS

After the WebView is created, we can get a WebViewController. Through its evaluateJavascript() method, we can execute JS statements:

onWebViewCreated: (WebViewController webViewController) {
 _controller = webViewController;
},
······
floatingActionButton: FloatingActionButton(
  onPressed: () {
   _controller
    ?.evaluateJavascript('callJS("visible")')
    ?.then((result) {
     // You can handle JS result here.
    });
  },
  child: Text('call JS'),
  ),
 &lt;p  style="visibility:hidden;"&gt;
 Flutter Called JS.
 Flutter Called JS.
 Flutter Called JS.
 &lt;/p&gt;
 
function callJS(message){
 ("p1"). = message;
}

In the above example, after we click on floatingActionButton, we will execute the callJS() method in JS. The specific UI is reflected in: redisplaying the hidden paragraph. evaluateJavascript() return value is a Future, so we can receive the return value given to us by JS. Please read the official API comments for the return value format.

What should be noted here is that the evaluateJavascript() method, Flutter recommends that we execute it after the onPageFinished callback to ensure that all HTML has been loaded. Therefore, in actual development, the method I show here to directly assign the controller in onWebViewCreated is not advisable. It should be to use FutureBuilder and other methods to achieve more elegant (I have a complete example on Gist, you can take a look).

Source code

/yumi0629

Recommended debugging toolsAmaze UI , a magical website, generates debugging web pages with one click, you deserve it

Note: Please generate the initialUrl test address in the source code by yourself!

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.