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执行某些操作

官方提供了两个方法:runJavaScript、runJavaScriptReturningResult。后者可以向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("搜索完成");
        });
      },
    );
  }
相关推荐
传奇开心果编程12 小时前
【Flutter踩坑排雷】第25课:ScrollController 误用坑|跳转失效、监听泄漏与“控制器未附加”
android·flutter·ios·移动开发·跨平台·dart·声明式ui
程序员老刘17 小时前
Flutter 3.50更新,开发者应该关注什么?
flutter·ai编程·客户端
好的佩奇2 天前
Dart 之集合元素
android·flutter·dart
恋猫de小郭2 天前
Flutter 3.50 & Dart 3.14 发布,快来看看有什么更新吧
android·前端·flutter
喵个咪3 天前
GoWind CMS 拆解:Flutter 设计系统内核——双态 token、四档断点与自适应壳层
前端·flutter·交互设计
恋猫de小郭3 天前
Flutter 大小核优化又被回滚,然后又开新提案?
android·前端·flutter
好的佩奇4 天前
蓝牙之广播与扫描
android·flutter·蓝牙
wuxianda10304 天前
2026 苹果审核 4.3 (a) 被拒全解析|Guideline 4.3a spam 马甲包拒审原因 + 避坑方案
flutter·uni-app·苹果上架
恋猫de小郭4 天前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter