flutter 原生与 js 交互

1,680 阅读3分钟

启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

Flutter系列文章列表

  1. 2022年了,你还不会flutter!!!
  2. Flutter 第一课---flutter特点及组件开发
  3. Flutter 第二课---组件生命周期和App生命周期
  4. Flutter 第三课---状态管理之Provide
  5. Flutter 第四课---路由管理
  6. Flutter 第五课 --- 包管理器和资源管理
  7. Flutter 第六课 --- flutter网络请求
  8. Flutter 第七课 --- flutter 网络封装
  9. Flutter 第八课 ---使用 Flutter 构建 Web 应用
  10. 如何正确的在flutter中添加webview

前言

今天讲的这个话题就很有趣,是关于flutter与js的交互,这也是基本刚需,为我们把原生项目编译H5打好基础,只有这样,我们所使用的热更新才会更加完美。我们今天用到的插件是webview_flutter

webview_flutter

简单介绍一下插件api

  • onWebViewCreated:在WebView创建完成后调用,只会被调用一次;
  • initialUrl:初始load的url;
  • javascriptMode:JS执行模式(是否允许JS执行);
  • javascriptChannels:JS和Flutter通信的Channel;
  • navigationDelegate:路由委托(可以通过在此处拦截url实现JS调用Flutter部分);
  • onPageFinished:WebView加载完毕时的回调。

JS调用Flutter

JS调用Flutter有两种方法:使用javascriptChannels发送消息和使用路由委托(navigationDelegate)拦截url。今天的主角是使用javascriptChannels发送消息,关于路由委托的学习后再未来的文章中讲述

flutter中加载webview

关于这个话题我在上一篇文章中已经做过详细解释。javascriptChannels参数可以传入一个对象,对象中有一个属性onMessageReceived,它的值是一个函数,函数的形参就是js传递给flutter的参数(包括回调函数名)

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

class WebviewApp extends StatefulWidget {
  const WebviewApp({Key? key}) : super(key: key);

  @override
  State<WebviewApp> createState() => _WebviewAppState();
}

class _WebviewAppState extends State<WebviewApp> {
  late WebViewController controller;

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) WebView.platform = AndroidWebView();
  }

  @override
  Widget build(BuildContext context) {
    return WebView(
      initialUrl: 'https://jolly-twilight-a037fd.netlify.app/',  // 这是是js文件线上地址
      javascriptMode: JavascriptMode.unrestricted,
      onWebViewCreated: (WebViewController webViewController) async {
        controller = webViewController;
      },
      javascriptChannels: <JavascriptChannel>{
        JavascriptChannel(
            name: "handleMessage",
            onMessageReceived: (JavascriptMessage message) async {
              print("flutter 调用了js,参数是${message.message}");  //  {"function":"getFlutterData","params":{"operation":"分享"}}  getFlutterData 就是回调函数
              var functionName = jsonDecode(message.message)["function"];
              return  controller.runJavascript("$functionName('123465789')");  // flutter 返回参数给js (js端显示打印结果是:"flutter 返回参数是 123465789")
            })
      },
    );
  }
}

附上js线上代码(防止误删你们看不到)

最重要的就是需要再js 端实现回调函数,不然flutter跟js的交互,就无法相互传递参数了

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div style="margin-top: 20px">
    <h2 id="aaaa">JS与Flutter交互</h2>
    <input type="button" value="唤起本地方法" onclick=inputClick()>
  </div>
</body>

<script>
  function inputClick () {
    handleMessage.postMessage(JSON.stringify({
      function: "getFlutterData",
      params: {operation: '分享' }
    }))
  }

  function getFlutterData(data){
    console.log("flutter 返回参数是", data);
  }

</script>

</html>

image.png

在上面的例子中,evaluateJavascript()返回值是一个Future,因此我们可以接收JS给我们的返回值,返回值格式请阅读官方API注释。 这里要注意的是,evaluateJavascript()方法,Flutter建议我们在onPageFinished回调之后去执行,以保证所有的HTML都已经加载完毕了。

结束语

关于flutter调用js的简使用,到这就结束了,如果你有什么疑问,可以在评论区留下问题或者私信我,如果你是很出色flutter的大佬,还希望得到你的指导和肯定。