前言
据我所知,真正掌握Flutter的Android开发工程师的比例并不是很高,如果你不这么认为,可能是因为你的圈子比较高端。你知道Android原生开发工程师把所有知识体系融汇贯通需要的时间是多久吗?当然这里把Flutter排除在外。资质顶尖的至少要3年,而大部分人智商属于中等偏上,大概要5年。如果是一个普通的码农,可能要8~10年甚至更久。当然我只是按之前非AI时代来进行估计的,未来AI时代可能会略有降低。10年啊,也就是一个普通的程序员需要从毕业干到快35岁危机时才能真正腾出精力来仔细研究Flutter这种跨平台的技术。当然你说我一开始的目标就是Flutter,那没问题,这不在讨论的范畴。
很多安卓开发其实压根没有练手Flutter项目的机会,因为,小公司很难招到这种十年以上的大佬。当然也不会有人从全局角度带你玩转Android Flutter混合开发,除非你运气好,正好有人带。
引入正题
如果完全没接触过Android Flutter混合开发的同学需要先看我这篇文章juejin.cn/post/725412... 。混合开发要想真正落地,不仅需要扎实的原生开发功底,还需要有刻苦钻研新技术的勇气。混合开发避不开一个话题,如何进行通信或者说相互调用的互操作性?这就引入了我们今天的主角------Method Channel。它直译过来就是方法通道,你可以理解成一个调用另一端方法的桥梁。我们看一下怎么写。
通信流程
原生调Dart
kt
val intent = FlutterActivity
.withNewEngine()
.initialRoute(ROUTE_HOME)
.build(this)
intent.setClass(this, MyFlutterActivity::class.java)
startActivity(intent)
先启动Flutter界面的原生壳Activity,清单文件该注册注册。
kt
package com.doracrypto.crypto.ui.activity
import android.content.Intent
import com.doracrypto.crypto.AppConfig
import dora.util.SPUtils
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MyFlutterActivity : FlutterActivity() {
companion object {
private const val CHANNEL = "com.doracrypto.crypto/native"
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"isVipUser" -> {
result.success(SPUtils.readBoolean(context, AppConfig.IS_VIP))
}
"startBuyVipActivity" -> {
startActivity(Intent(this@MiniAppActivity, BuyVipActivity::class.java))
result.success(null)
}
else -> result.notImplemented()
}
}
}
}
这东西虽不难,但确是必经之路。在原生侧,我们需要提供各种各样的方法给Dart侧调用。
dart
import 'package:flutter/services.dart';
class MethodChannelPlugin {
static const MethodChannel methodChannel = MethodChannel('com.doracrypto.crypto/native');
// /// 调用原生浏览器组件
// static Future<void> gotoWebView(String url) async {
// try {
// await methodChannel.invokeMethod('gotoWebView',{'url': url});
// } on PlatformException {
// print('Failed go to gotoWebView');
// }
// }
/// 检测是否是VIP用户
static Future<bool> isVipUser() async {
try {
final result = await methodChannel.invokeMethod('isVipUser');
return result == true; // 保证返回 bool
} on PlatformException catch (e) {
print('Failed isVipUser: $e');
return false; // 出错时兜底返回 false
} catch (e) {
print('Unexpected error in isVipUser: $e');
return false;
}
}
/// 跳转购买VIP界面
static Future<void> startBuyVipActivity() async {
try {
await methodChannel.invokeMethod('startBuyVipActivity');
} on PlatformException catch (e) {
print('Failed startBuyVipActivity: $e');
} catch (e) {
print('Unexpected error in startBuyVipActivity: $e');
}
}
}
调用时就这样去调。
dart
bool isVip = await MethodChannelPlugin.isVipUser();
if (!isVip) {
MethodChannelPlugin.startBuyVipActivity();
return;
}
Dart调原生
主要都是Dart调原生,原生调用Dart的场景不是很多。不多但不代表没有,我这里简单提一嘴。
dart
import 'package:flutter/services.dart';
class NativeBridge {
static const MethodChannel _channel = MethodChannel("com.doracrypto.crypto/dart");
static void init() {
// 接收原生调用
_channel.setMethodCallHandler((call) async {
if (call.method == "fromNative") {
String msg = call.arguments as String;
print("收到原生调用:$msg");
return "Dart收到: $msg";
}
return null;
});
}
}
在main.dart里面初始化。
dart
void main() {
// 等待初始化完成
WidgetsFlutterBinding.ensureInitialized();
NativeBridge.init();
runApp(MyApp());
}
原生侧调用Dart。
kt
class MainActivity: FlutterActivity() {
private lateinit var channel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
"com.doracrypto.crypto/dart"
)
Handler(Looper.getMainLooper()).postDelayed({
channel.invokeMethod("fromNative", "Hello from Android")
}, 3000)
}
}
通道名称只要唯一就行,并不一定要这样的格式。最后编译aar,三行命令,搞定。
bash
flutter clean
flutter pub get
flutter build aar
把编译出的aar包依赖进原生项目就大功告成了,最后正常走打原生包的流程。
写在最后
Flutter是真正的好东西,对创业者相当友好,达到高级开发后,大大节省开发和维护时间,因为只维护一份代码。当你把核心算法用Dart实现后,原生的壳实际上是可以下发给别人开发的,这又进一步节省了开发时间,前提是你的项目先要稳定盈利。欢迎体验混合开发出的app www.pgyer.com/cryptotools 。