flutter开发实战-inappwebview实现flutter与Javascript方法调用

flutter开发实战-inappwebview实现flutter与Javascript方法调用

在使用inappwebview时候,需要flutter端与JS进行交互,调用相应的方法,在inappwebview中的JavaScript Handlers。

一、JavaScript Handlers

要添加JavaScript Handlers,可以使用InAppWebViewController.addJavaScriptHandler方法,在该方法中定义handlerName和JavaScript端调用它时要调用的回调。回调可以返回要在JavaScript端发送的数据。如果您需要在加载网页后立即管理JavaScript处理程序,则应在创建InAppWebView时调用InAppWebViewController.addJavaScriptHandler。

以下是如何注册JavaScript处理程序的示例:

复制代码
onWebViewCreated: (controller) {
  // register a JavaScript handler with name "myHandlerName"
  controller.addJavaScriptHandler(handlerName: 'myHandlerName', callback: (args) {
    // print arguments coming from the JavaScript side!
    print(args);

    // return data to the JavaScript side!
    return {
      'bar': 'bar_value', 'baz': 'baz_value'
    };
  });
},

在JavaScript端,要执行回调处理程序并将数据发送到Flutter,您需要使用window.Flutter_inappwebview.callHandler(handlerName,...args)方法,其中handlerName是一个字符串,表示您正在调用的处理程序名称,args是可以发送到Fluter方面的可选参数。

注意:

如果相更换一个名字,我们可以更换一个名字来嵌套window.flutter_inappwebview

window.myCustomObj = { callHandler: window.flutter_inappwebview.callHandler } and, then, you can use window.myCustomObj.callHandler

此外,可以通过这种方式包装整个特定的处理代码:

const myHandlerName = (...args) => window.flutter_inappwebview.callHandler('myHandlerName', ...args);

然后调用myHandlerName();

在Javascript端,如果需要调用callHandler,需要监听flatterInAppWebViewPlatformReady。可以使用在flatterInAppWebViewPlatformReady事件被分派时设置的全局标志变量,并在调用window.flutter_inappwebview.callHandler方法之前使用它。

示例代码如下

复制代码
// execute inside the "flutterInAppWebViewPlatformReady" event listener
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
 const args = [1, true, ['bar', 5], {foo: 'baz'}];
 window.flutter_inappwebview.callHandler('myHandlerName', ...args);
});

// or using a global flag variable
var isFlutterInAppWebViewReady = false;
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
 isFlutterInAppWebViewReady = true;
});
// then, somewhere in your code
if (isFlutterInAppWebViewReady) {
 const args = [1, true, ['bar', 5], {foo: 'baz'}];
 window.flutter_inappwebview.callHandler('myHandlerName', ...args);
}

在flutter端,Flutter在执行注入方法时候,调用evaluateJavascript来执行callHandler,这个flutterInAppWebViewPlatformReady无需监听,因为这个flutterInAppWebViewPlatformReady已经Ready了。

可以在onLoadStop中调用代码

复制代码
onLoadStop: (controller, url) async {
  await controller.evaluateJavascript(source: """
    const args = [1, true, ['bar', 5], {foo: 'baz'}];
    window.flutter_inappwebview.callHandler('myHandlerName', ...args);
  """);
},

window.flutter_inappwebview.callHandler返回一个JavaScript Promise,该Promise可用于获取回调返回的json结果。在这种情况下,只需返回您想要发送的数据,它将使用dart:convert库中的jsonEncode自动进行json编码。

一个简单的示例代码

复制代码
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (Platform.isAndroid) {
    await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
  }
  
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
      android: AndroidInAppWebViewOptions(
        useHybridComposition: true,
      ),);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(title: Text("JavaScript Handlers")),
          body: SafeArea(
              child: Column(children: <Widget>[
                Expanded(
                  child: InAppWebView(
                    initialData: InAppWebViewInitialData(
                        data: """
<!DOCTYPE html>
<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 Handlers</h1>
        <script>
            window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
                window.flutter_inappwebview.callHandler('handlerFoo')
                  .then(function(result) {
                    // print to the console the data coming
                    // from the Flutter side.
                    console.log(JSON.stringify(result));
                    
                    window.flutter_inappwebview
                      .callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}, result);
                });
            });
        </script>
    </body>
</html>
                      """
                    ),
                    initialOptions: options,
                    onWebViewCreated: (controller) {
                      controller.addJavaScriptHandler(handlerName: 'handlerFoo', callback: (args) {
                        // return data to the JavaScript side!
                        return {
                          'bar': 'bar_value', 'baz': 'baz_value'
                        };
                      });

                      controller.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) {
                        print(args);
                        // it will print: [1, true, [bar, 5], {foo: baz}, {bar: bar_value, baz: baz_value}]
                      });
                    },
                    onConsoleMessage: (controller, consoleMessage) {
                      print(consoleMessage);
                      // it will print: {message: {"bar":"bar_value","baz":"baz_value"}, messageLevel: 1}
                    },
                  ),
                ),
              ]))),
    );
  }
}

二、监听自定义CustomEvent

可以设置一个消息事件侦听器(与postMessage一起使用)或一个自定义事件侦听器。

复制代码
// message event listener
window.addEventListener("message", (event) => {
  console.log(event.data);
}, false);

// or custom event listener
window.addEventListener("myCustomEvent", (event) => {
  console.log(event.detail);
}, false);

然后使用window.dispatch

复制代码
// using postMessage method
window.postMessage({foo: 1, bar: false});

// or dispatching a custom event
const event = new CustomEvent("myCustomEvent", {
    detail: {foo: 1, bar: false}
});
window.dispatchEvent(event);

因此,可以在运行时使用InAppWebViewController.eevaluatteJavascript方法或在web应用程序内部设置这些事件侦听器,并使用相同的方法调度这些事件。

例如:

复制代码
onLoadStop: (controller, url) async {
  await controller.evaluateJavascript(source: """
    window.addEventListener("myCustomEvent", (event) => {
      console.log(JSON.stringify(event.detail));
    }, false);
  """);

  await Future.delayed(Duration(seconds: 5));

  controller.evaluateJavascript(source: """
    const event = new CustomEvent("myCustomEvent", {
      detail: {foo: 1, bar: false}
    });
    window.dispatchEvent(event);
  """);
},
onConsoleMessage: (controller, consoleMessage) {
  print(consoleMessage);
  // it will print: {message: {"foo":1,"bar":false}, messageLevel: 1}
},

三、小结

flutter开发实战-inappwebview实现flutter与Javascript方法调用。描述可能不是特别准确,请见谅。

学习记录,每天不停进步。

相关推荐
福兮说8 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
凤城老人9 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)10 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan10 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_11 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
yivifu12 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
weixin_4482902512 小时前
书庐开发实战教学
javascript·css·html
默_笙12 小时前
🛴 从散件到整机:DeepAgents 与 Agent 身上预留的那些"插槽"(前置介绍)
前端·javascript
一木 之林13 小时前
DeepSeek Agent 开发(一)
开发语言·前端·javascript
樱花落木兰15 小时前
分布式登录实战:Session 会话共享改造,Redis 存储用户登录状态
java·javascript·数据库·redis·分布式·缓存