🐦 Flutter 移动端开发

Flutter 是 Google 推出的跨平台 UI 框架,使用 Dart 语言,一套代码可同时运行在 iOS 和 Android 平台。与 Web 技术栈不同,Flutter 自绘引擎提供接近原生的高性能体验。

Flutter vs React Native vs Web 对比

维度FlutterReact Native移动端 Web (H5)
渲染方式 Skia 自绘引擎 桥接到原生组件 浏览器 WebView 渲染
性能 ⭐⭐⭐⭐⭐ 接近原生 ⭐⭐⭐⭐ 需优化 Bridge ⭐⭐⭐ 受限于 WebView
开发语言 Dart JavaScript / TypeScript HTML + CSS + JavaScript
热重载 ✅ 秒级 Hot Reload ✅ Fast Refresh ✅ 浏览器自动刷新
UI 一致性 ⭐⭐⭐⭐⭐ 像素级一致 ⭐⭐⭐ 依赖原生组件 ⭐⭐ 浏览器差异大
包管理 pub.dev (30,000+) npm (海量) npm (海量)
学习曲线 中等(需学 Dart + Widget) 低(前端开发者友好) 低(前端基础即可)
适用场景 高性能跨平台 App 快速迭代的跨平台 App 营销页、内嵌 H5、混合 App

Flutter 与 WebView 混合开发

在实际项目中,经常需要在 Flutter 中嵌入 H5 页面,或 H5 页面调用 Flutter 原生能力。

// ===== Flutter 中嵌入 H5(WebView)=====
import 'package:webview_flutter/webview_flutter.dart';

class H5Page extends StatefulWidget {
  @override
  State<H5Page> createState() => _H5PageState();
}

class _H5PageState extends State<H5Page> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (url) {
            // 页面加载完成后注入 JS
            _controller.runJavaScript('console.log("Flutter 注入的代码")');
          },
        ),
      )
      // Flutter ↔ H5 双向通信
      ..addJavaScriptChannel('FlutterBridge',
        onMessageReceived: (message) {
          // 接收 H5 发来的消息
          print('H5 发来消息: ${message.message}');
        },
      )
      ..loadRequest(Uri.parse('https://your-h5-page.com'));
  }

  // 原生调用 H5
  void callJSFunction(String data) {
    _controller.runJavaScript('window.onFlutterMessage($data)');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('H5 页面')),
      body: SafeArea(
        child: WebViewWidget(controller: _controller),
      ),
    );
  }
}

// ===== H5 端调用 Flutter(JavaScript)=====
// 在 H5 页面中发送消息给 Flutter
function sendToFlutter(action, params) {
  if (window.FlutterBridge) {
    FlutterBridge.postMessage(JSON.stringify({ action, params }));
  }
}

// 接收 Flutter 发来的消息
window.onFlutterMessage = function(data) {
  console.log('Flutter 发来消息:', data);
};

Flutter ↔ WebView 混合开发避坑指南

坑点问题描述解决方案
JS Bridge 未就绪 H5 页面过早调用 FlutterBridge.postMessage(),但 Bridge 还未注入完成,导致消息丢失 H5 端轮询等待 Bridge 就绪,或 Flutter 在 onPageFinished 后主动通知 H5
键盘遮挡 WebView H5 内输入框聚焦时键盘弹出,WebView 不会自动调整,导致输入框被遮挡 设置 resizeToAvoidBottomInset: true(Scaffold 默认),或手动监听 viewInsets 调整 padding
Android 与 iOS WebView 差异 webview_flutter 在 Android 用 Chromium,iOS 用 WKWebView,部分 JS/CSS 行为不一致 关键功能两端测试;避免使用 WebKit 私有 API;使用 flutter_inappwebview 替代可获得更统一的行为
返回键拦截 用户在 WebView 中浏览多页后按返回键,直接退出了整个页面而非返回 H5 上一页 使用 WillPopScope(或 PopScope)拦截返回事件,先判断 _controller.canGoBack(),有历史则 goBack()
Cookie 同步 Flutter 原生登录态(Token)需要同步到 WebView,否则 H5 需要重新登录 通过 JS Bridge 传递 Token,H5 写入 localStorage;或加载 URL 时在 Header 中注入 Cookie
白屏/加载慢 H5 页面网络慢或资源大时,WebView 长时间白屏,体验差 Flutter 端先展示骨架屏/Native Loading;设置 onPageFinished 后切换;H5 端启用资源预加载和离线缓存
内存泄漏 WebView 未正确释放,反复进出页面后内存持续增长,导致 App 卡顿或 Crash dispose() 中调用 _controller.clearCache() 等清理;避免在多个页面中重复创建 WebView;及时移除 JS Channel
HTTPS 混合内容 H5 页面为 HTTPS,但内部引用了 HTTP 资源(图片、接口),在 iOS WKWebView 中默认被拦截 H5 端所有资源统一使用 HTTPS;Flutter 端可配置 App Transport Security 例外(仅开发调试用)
文件上传/下载 H5 中的 <input type="file"> 在 WebView 中默认无法触发 使用 flutter_inappwebview 处理文件选择回调;或通过 JS Bridge 由 Flutter 原生端实现文件选择和上传
调试困难 WebView 中的 H5 控制台、网络请求无法直接查看,排查问题效率低 Android: Chrome chrome://inspect 远程调试;iOS: Safari 开发菜单中连接 WebView;Flutter 端开启 onConsoleMessage 回调打印日志