一、Flutter与Android生态概览
各位同学,今天我们来聊聊Flutter和Android这对“欢喜冤家”。
说实话,我在移动端摸爬滚打了快十年,从早期的Eclipse+ADT,到Android Studio,再到Flutter横空出世,每一步都踩过坑。这门课的第一章,我想先带大家把整个生态看清楚——你只有知道来龙去脉,才知道怎么搭架构。
1.1 Flutter发展史:从“小试牛刀”到“企业级标配”
Flutter是Google在2015年Dart开发者峰会上首次亮相的。当时我还在做原生开发,第一反应是:“又一个跨平台框架?”说实话,那会儿React Native正火,Flutter看起来像个“后来者”。
但2018年Flutter 1.0正式发布后,我认真试了一把。嗯,真香。
为什么?因为Flutter不走寻常路——它没有用WebView,也没有桥接原生控件,而是自己用Skia引擎从头画UI。这意味着什么?说白了,你的界面在iOS和Android上长得一模一样,而且性能接近原生。
关键里程碑:
- 2015年:Flutter预览版发布,代号“Sky”
- 2018年:Flutter 1.0正式版,支持iOS和Android
- 2021年:Flutter 2.0,支持Web和桌面端
- 2023年:Flutter 3.x,Impeller渲染引擎逐步替代Skia
我个人习惯把Flutter的发展分为三个阶段:探索期(2015-2018)、成长期(2018-2021)、成熟期(2021至今)。现在你看到的Flutter,已经是一个能支撑千万级日活应用的成熟框架了。
1.2 Android原生架构回顾:别以为你忘了
在讲协同之前,我们得先回顾一下Android原生架构。你可能会想:“这我早就会了。”但我在项目中遇到过不少同学,Flutter写得很溜,一碰到原生交互就懵了。
Android原生架构,核心就三层:
| 层级 | 说明 | 我踩过的坑 |
|---|---|---|
| 应用层 | Activity、Fragment、Service等 | Activity生命周期管理不当,导致Flutter页面闪退 |
| 框架层 | View体系、资源管理、ContentProvider | 自定义View与Flutter渲染冲突 |
| 系统层 | Linux内核、硬件抽象层(HAL) | 权限申请时机不对,引发ANR |
你想想看,Flutter其实是在应用层之上又加了一层自己的渲染引擎。所以协同的关键,就是让这两套体系“和平共处”。
小提示:如果你对Android原生不太熟,建议先复习一下Activity的启动模式和生命周期。我在做混合工程时,80%的Bug都出在这上面。
1.3 Flutter与原生协同的三种模式
好了,重头戏来了。Flutter和Android原生到底怎么协同?我把它总结为三种模式。这三种模式,你都得会——因为实际项目中,往往三种混着用。
模式一:Platform Channel(平台通道)
这是Flutter官方主推的方式。Flutter通过MethodChannel、EventChannel、BasicMessageChannel与原生端通信。
举个例子,你要获取设备的电池电量:
// Flutter端
static const platform = MethodChannel('samples.flutter.dev/battery');
try {
final int result = await platform.invokeMethod('getBatteryLevel');
print('电池电量: $result%');
} catch (e) {
print('获取失败: $e');
}
// Android端(MainActivity.kt)
channel.setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
result.success(batteryLevel)
} else {
result.notImplemented()
}
}
我曾经在一个金融项目中,用Platform Channel实现了指纹识别和Face ID的调用。注意,这里有个坑:不要在UI线程做耗时操作。我曾经见过同事直接在MethodCallHandler里做网络请求,结果界面卡死——嗯,血的教训。
避坑指南:Platform Channel是异步的,但如果你在主线程同步等待结果,Flutter的UI线程会被阻塞。我曾经因为这个原因,导致页面切换动画掉帧。解决方案:用async/await,或者把耗时操作放到后台线程。
模式二:Flutter Boost
Flutter Boost是闲鱼团队开源的一套方案。它的核心思想是:把Flutter页面当作一个“View”来管理。
为什么需要它?因为在实际项目中,你不可能一下子把所有页面都改成Flutter。往往是原生页面和Flutter页面混着用。Flutter Boost帮你解决了页面路由和生命周期管理的问题。
我记得有一次,一个电商App要接入Flutter的商品详情页。如果用原生路由,Activity跳来跳去,内存管理一团糟。用了Flutter Boost后,Flutter页面就像原生Fragment一样,随用随取,随走随销毁。
Flutter Boost的核心优势:
- 原生和Flutter页面共享路由栈
- Flutter页面生命周期与原生同步
- 支持页面间传参和回调
模式三:混合工程(Hybrid Engineering)
这是最灵活,也最复杂的一种模式。说白了,就是把Flutter模块作为一个Library,嵌入到原生工程中。
我建议用这种方式来组织代码:
项目根目录/
├── app/ # 原生Android工程
│ ├── src/main/
│ └── build.gradle
├── flutter_module/ # Flutter模块
│ ├── lib/
│ ├── pubspec.yaml
│ └── build.gradle
└── settings.gradle # 引入flutter_module
为什么推荐混合工程?因为你可以渐进式迁移。先在一个小功能上试试Flutter,没问题了再逐步扩大。我在一个日活百万的App上就是这么干的——先做了“用户反馈”页面,然后是“设置页”,最后是整个“个人中心”。
但注意,混合工程有个大坑:构建配置。Flutter和Android的Gradle版本要匹配,否则编译报错能让你怀疑人生。我曾经花了一整天,就为了对齐两个版本的依赖。
我的建议:如果你是新项目,直接用Flutter纯工程。如果是老项目改造,优先用Flutter Boost,等稳定了再考虑混合工程。别一上来就搞混合工程——我见过太多团队死在这上面。
知识体系总览
下面这张图,是我自己画的Flutter与Android协同的知识体系。你可以把它当作整个课程的地图:
这张图我画了很久,就是想让你一眼看清整个知识结构。后面的章节,我们会逐一深入每个模块。别急,慢慢来。
本章小结:
- Flutter从2015年走到今天,已经是一个成熟的跨平台方案
- Android原生架构是协同的基础,别忽视它
- Platform Channel适合功能调用,Flutter Boost适合页面管理,混合工程适合渐进式迁移
- 选哪种模式,取决于你的项目现状和团队能力
好了,第一章就到这里。下一章我们会深入Platform Channel的底层原理,到时候我会带你看MethodChannel的源码——嗯,保证让你大开眼界。