前言
最近在研究如何在应用程序中嵌入Web视图,发现有两个库不错。
一个是官方维护、一个是第三方维护。因为没说特别的需求,就使用了官方库,实现一些简单功能是完全ok的
基本使用
官方文档
https://pub-web.flutter-io.cn/packages/webview_flutter
安装
flutter pub add webview_flutter
加载并显示web
可以加载html字符串,也可以直接加载url链接。官方都提供了对应的方法,这里演示加载url
- 初始化
late WebViewController webViewController;
//初始化
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执行某些操作
官方提供了两个方法:runJavaScript
、runJavaScriptReturningResult
。后者可以向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)
''');
}));