flutter:webview_flutter和flutter_inappwebview的简单使用

无知的小菜鸡 2024-06-30 12:33:02 阅读 61

前言

最近在研究如何在应用程序中嵌入Web视图,发现有两个库不错。

在这里插入图片描述

一个是官方维护、一个是第三方维护。因为没说特别的需求,就使用了官方库,实现一些简单功能是完全ok的

webview_flutter

不建议使用,因为效果不怎么样,当然也可能是我太菜不会用,下面这个问题就很难理解为什么会这样?

在这里插入图片描述

基本使用

官方文档

https://pub-web.flutter-io.cn/packages/webview_flutter

安装

flutter pub add webview_flutter

加载并显示web

可以加载html字符串,也可以直接加载url链接。官方都提供了对应的方法,这里演示加载url

初始化

late WebViewController webViewController;

//初始化

@override

void initState() {

super.initState();

webViewController = WebViewController()

..setJavaScriptMode(JavaScriptMode.unrestricted);

}

显示

显示的时候一般需要结合FutureBuilder,比较这是一个异步的过程

FutureBuilder(

// 异步方法

future: searchNovelFromWeb(),

builder: (context, snapshot) {

// 等待状态显示的widget

if (snapshot.connectionState == ConnectionState.waiting) {

return const Center(

child: CircularProgressIndicator(),

);

// 错误时显示的widget

} else if (snapshot.hasError) {

return const Text('Error');

} else {

return snapshot.data ?? const Text('No data');

}

}))

Future<Widget> searchNovelFromWeb() async {

Widget res;

try {

await webViewController

.loadRequest(Uri.parse('https://m.bbxxxxxx.com/s?q=凡人修仙'));

res = WebViewWidget(controller: webViewController);

} catch (error) {

res = Text("加载失败:${ error.toString()}");

print("加载失败:${ error.toString()}");

}

return res;

}

在这里插入图片描述

在这里插入图片描述

flutter与web之间的交互

flutter通知web,让web执行某些操作

官方提供了两个方法:runJavaScriptrunJavaScriptReturningResult。后者可以向flutter返回执行结果

比如在网页加载完成后获取到网页源代码

webViewController.setNavigationDelegate(

NavigationDelegate(onPageFinished: (url) async {

print("页面加载完成:$url");

var html = await webViewController.runJavaScriptReturningResult(

"document.documentElement.innerText;");

debugPrint("结果是11:$html", wrapWidth: 1024);

}));

在这里插入图片描述

web发生变化后,通知flutter

这块也实现了,但是不太稳定,有时候不能够正常运行

await webViewController

.loadRequest(Uri.parse('https://m.bbxxxxxxxt.com/s?q=凡人修仙'));

webViewController.setNavigationDelegate(

NavigationDelegate(onPageFinished: (url) async {

print("页面加载完成:$url");

// 添加监听

await webViewController.addJavaScriptChannel('Report',

onMessageReceived: (JavaScriptMessage message) {

print("收到了消息,是:${ message.message}");

});

// 注入脚本

await webViewController.runJavaScript('''

setInterval(() => {

let time = new Date().toLocaleTimeString();

Report.postMessage(time);

},1000)

''');

}));

在这里插入图片描述

flutter_inappwebview

功能更多,这里只会简单介绍一下,具体使用可以查看官方文档、官方案例。

强烈推荐:功能更多,而且原来使用webview_flutter无法实现的功能,现在轻而易举的实现了。

官方文档

官方案例

安装

flutter pub add flutter_inappwebview

基本使用

这里遇到个问题,版本过高导致构建失败了。我现在用的版本是:5.6.0

// 将html字符串解析为dom的库

import 'package:html/parser.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

late InAppWebViewController inAppWebViewController;

res = InAppWebView(

initialUrlRequest:

URLRequest(url: Uri.parse('https://onion.inscode.cc/')),

onLoadStop: (controller, url) async {

// 加载完成

inAppWebViewController = controller;

print("加载地址:$url");

var html = await controller.getHtml();

debugPrint("html是:${ html.toString().trim()}");

var dom = parse(html);

print("标题是:${ dom.querySelector('.title')?.text}");

},

);

在这里插入图片描述

执行脚本

要等页面加载完成后才能执行

// 执行脚本

var body = await inAppWebViewController.evaluateJavascript(

source: "document.body.innerHTML");

debugPrint("执行结果:${ body.toString().trim()}");

在这里插入图片描述

遇到的问题

最开始我的想法是执行函数,然后更新要显示的组件,但是resBody 一直没有更新。后来发现好像是onLoadStop没有执行,仔细思考后应该是InAppWebView初始化后,没有在页面上显示导致后续方法没有执行。解决方法就是让InAppWebView在页面上显示,当然可能不想在页面显示,这时给它父容器设置一个高度比如1,这样就可以解决这个问题。

Future searchNovelFromWeb() async {

String html = '';

InAppWebView(

initialUrlRequest:

URLRequest(url: Uri.parse('https://onion.inscode.cc/')),

onLoadStop: (controller, url) async {

inAppWebViewController = controller;

print("开始搜索了");

html = await inAppWebViewController.getHtml() ?? '1111';

debugPrint("查询的值:${ html.toString()}");

setState(() {

resBody = const Text("搜索完成");

});

},

);

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。