Flutter WebView 和JavaScript 交互


flutter官方并没有提供WebView组件,不过官方的plugin库给我们提供了webview_flutter插件,集成到我们的项目中就可以使用了

一、集成

在项目的pubspec.yaml文件中添加一下代码
webview_flutter: ^0.3.19+6

二、简单使用

var webUrl ="http://192.168.10.120:8081/test.html?time=${DateTime.now()};
return Scaffold(
    appBar: AppBar(title: Text('WebView')),
    body: Builder(builder: (BuildContext context) {
      return WebView(
        initialUrl: webUrl,
        onWebViewCreated: (WebViewController controller) {
          _controller = controller;
        },
        onPageStarted: (String url) {},
        onPageFinished: (String url) {},
      );
    }));
    }

三、Js 调用Flutter(两种方法)

方法一、使用javascriptChannels发送消息

  • Flutter代码

  • 定义javascriptChannels JavascriptChannel方法中的两个参数,name是和js协商的标记,onMessageReceived当js收到Flutter发送的消息时的回调

    JavascriptChannel _alertJavascriptChannel(BuildContext context) {
        return JavascriptChannel(
                name: 'MyApp',
                onMessageReceived: (JavascriptMessage message) {
                //js 收到了Flutter发送的消息
                showToast(message.message);
              });
        }
    
    WebView(
    javascriptChannels: <JavascriptChannel>[
        _alertJavascriptChannel(context),
    ].toSet(),
  • js代码

    <button onclick="callFlutter()">callFlutter</button>
        function callFlutter(){
        // MyApp为Flutter定义的name
        MyApp.postMessage("JS调用了Flutter");
    }

方法二、使用路由委托navigationDelegate拦截url

  • Flutter代码
    在Flutter端,我们就可以在navigationDelegate回调中拦截这个符合js://webviewscheme的路由地址了:

    navigationDelegate: (NavigationRequest request) {
        if (request.url.startsWith('js://html')) {
          showToast('JS调用了Flutter By navigationDelegate');
          print('blocking navigation to $request}');
          return NavigationDecision.prevent;  //阻止路由替换
        }
        print('allowing navigation to $request');
        return NavigationDecision.navigate; //允许路由替换
      },
  • js代码

    <button onclick="callFlutter()">callFlutter</button>
    function callFlutter(){
    var url = "js://html?params1=111&params2=222"
    //url 为两端定义的协议
    document.location = url;
    }

    四、Flutter 调用JS

  • 在实际开发中免不了和js的数据交互,例如js需要拿到app登录的用户信息,这时候我们在Flutter端收到请求以后,可以通过拿到一个WebViewController,通过它的evaluateJavascript()方法,然后将我们的用户信息传递给js,具体代码如下:

  • Flutter 代码

    onWebViewCreated: (WebViewController webViewController) {
    _controller = webViewController;
    },
    JavascriptChannel _alertJavascriptChannel(BuildContext context) {
        return JavascriptChannel(
                name: 'MyApp',
                onMessageReceived: (JavascriptMessage message) {
                showToast(message.message);
                // js 告诉Flutter需要获取用户信息
                if(message.messageType == "getUserInfo"){
                    //Flutter把用户信息传递到js
                    var userInfo = User("username","token");
                    String userString = json.encode(userInfo);
                    controller
                    ?.evaluateJavascript('getUserInfo($userString)')
                    ?.then((result) {
    
                    });
                    }
              });
        }
  • js 代码

    <button onclick="callFlutter()">获取用户信息</button>
    <script>
        function callFlutter() {
            // 我需要用户信息
            var str = navigator.userAgent;
            if (str.includes('MyApp')) { // 此处为Flutter端JavascriptChannel定义的name
                MyApp.postMessage(JSON.stringify({ method: "getUserInfo" }));
            } else {
                $('body').html('<p>hello world</p>');
            }
        }
    
        function getUserInfo(message) {
            var data = JSON.parse(JSON.stringify(message)) //注意此处json的解析方式
            document.getElementById("p1").textContent = data.userUid;
            document.getElementById("p2").textContent = data.username;
            document.getElementById("p3").textContent = data.userType;
            document.getElementById("p4").textContent = data.realName;
        }
    </script>

    五、补充

  • 在实际项目中,我们需要和js开发者定义交互的数据结构,例如:

    class JsBridgeModel {
        int type; //类型 例如 打开微信、获取用户信息等
        String message;
        var data;
    }
    
    JsBridgeModel(this.type,this.message,this.data);
    js端post发送消息的时候需要根据Flutter定义好的格式来
    XX.postMessage(JSON.stringify({ type: 1,message:"",data:{} }))

    五、总结:

  • Flutter和js交互的方式基本就是这样,如果你还有需要补充的可以在下方留言。


文章作者: bigshot
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 bigshot !
 上一篇
Flutter1.12升级后遇到的问题 Flutter1.12升级后遇到的问题
相信看过官方更新日志的小伙伴都知道新版本的flutter和Android原生交互有一些改变,主要在以下部分 1.自定义的Plugin类需要实现FlutterPlugin的接口,并实现以下两个方法 @Override public void
2020-04-02 bigshot
本篇 
Flutter WebView 和JavaScript 交互 Flutter WebView 和JavaScript 交互
flutter官方并没有提供WebView组件,不过官方的plugin库给我们提供了webview_flutter插件,集成到我们的项目中就可以使用了 一、集成在项目的pubspec.yaml文件中添加一下代码 webview_flutte
2020-04-01 bigshot
  目录