flutter:webview_flutter和flutter_inappwebview的简单使用

前言

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

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

webview_flutter

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

基本使用

官方文档

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

安装

dart 复制代码
flutter pub add webview_flutter

加载并显示web

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

  • 初始化
dart 复制代码
 late WebViewController webViewController;

  //初始化
  @override
  void initState() {
    super.initState();
    webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted);
  }
  • 显示
    显示的时候一般需要结合FutureBuilder,比较这是一个异步的过程
dart 复制代码
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返回执行结果

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

dart 复制代码
webViewController.setNavigationDelegate(
      NavigationDelegate(onPageFinished: (url) async {
    print("页面加载完成:$url");
       
     var html = await webViewController.runJavaScriptReturningResult(
       "document.documentElement.innerText;");
      debugPrint("结果是11:$html", wrapWidth: 1024);
  }));

web发生变化后,通知flutter

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

dart 复制代码
 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无法实现的功能,现在轻而易举的实现了。

官方文档

官方案例

安装

dart 复制代码
flutter pub add flutter_inappwebview

基本使用

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

dart 复制代码
// 将html字符串解析为dom的库
import 'package:html/parser.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

late InAppWebViewController inAppWebViewController;
dart 复制代码
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}");
   },
 );

执行脚本

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

dart 复制代码
 // 执行脚本
 var body = await inAppWebViewController.evaluateJavascript(
     source: "document.body.innerHTML");
 debugPrint("执行结果:${body.toString().trim()}");

遇到的问题

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

dart 复制代码
  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("搜索完成");
        });
      },
    );
  }
相关推荐
ujainu23 分钟前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
ujainu25 分钟前
让笔记触手可及:为 Flutter + OpenHarmony 鸿蒙记事本添加实时搜索(二)
笔记·flutter·openharmony
一只大侠的侠25 分钟前
Flutter开源鸿蒙跨平台训练营 Day 13从零开发注册页面
flutter·华为·harmonyos
一只大侠的侠38 分钟前
Flutter开源鸿蒙跨平台训练营 Day19自定义 useFormik 实现高性能表单处理
flutter·开源·harmonyos
恋猫de小郭2 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
一只大侠的侠6 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
renke336410 小时前
Flutter for OpenHarmony:色彩捕手——基于HSL色轮与感知色差的交互式色觉训练系统
flutter
子春一12 小时前
Flutter for OpenHarmony:构建一个 Flutter 四色猜谜游戏,深入解析密码逻辑、反馈算法与经典益智游戏重构
算法·flutter·游戏
铅笔侠_小龙虾12 小时前
Flutter 实战: 计算器
开发语言·javascript·flutter
微祎_14 小时前
Flutter for OpenHarmony:构建一个 Flutter 重力弹球游戏,2D 物理引擎、手势交互与关卡设计的工程实现
flutter·游戏·交互