flutter 从入门到放弃
背景
从搭建环境到项目开发,入坑flutter已经快一周了,不得不说,从android原生开发者角度来说,相对于其他的跨平台方案,不管是性能,UI渲染还是学习成本,flutter还是相对比较友好的,内部维护几套UI逻辑,skia引擎渲染,而不依赖于原生控件的局限性,Hotload开发快捷等等,但我们要明白一点,flutter始终是一个跨平台的UI方案,最终还是要根据平台生成.apk(android)/.ipa(ios)包的,所以在涉及到一些系统平台的接口或者数据,比如系统电量什么的,还是需要native层去搞定的,再将数据返回给flutter层去展示,所以难免就会出现flutter与native的通信问题,那么Flutter是如何做到的呢?答案是Platform Channels
Platform Channels

上图来自Flutter官网,表明了Platform Channels的架构示意图。有细心的同学就要问了,你不是说Flutter和Native通信是通过Platform Channels吗?怎么架构图里面连接他们的是MethodChannel? 其实呢,MethodChannel是Platform Channels中的一种,顾名思义,MethodChannel用起来应该和方法调用差不多。那么还有别的channel?有的,还有EventChannel,BasicMessageChannel等。如果你需要把数据从Native平台发送给Flutter,推荐你使用EventChannel。Flutter framework也是在用这些通道和Native通信
例子1:flutter调用android logcat
虽然flutter本身提供了2种日志输出方式,print(),debugprint(),但是对于android开发者来说还是不太习惯,而且信息冗余在console栏里面,没法过滤等等,所以可以通过这个Channels去调用android原生的logcat
Flutter端
import 'package:flutter/services.dart';
class LogUtils {
static const perform = const MethodChannel("android_log");
static void v(String tag, String message) {
perform.invokeMethod('logV', {'tag': tag, 'msg': message});
}
static void d(String tag, String message) {
perform.invokeMethod('logD', {'tag': tag, 'msg': message});
}
static void i(String tag, String message) {
perform.invokeMethod('logI', {'tag': tag, 'msg': message});
}
static void w(String tag, String message) {
perform.invokeMethod('logW', {'tag': tag, 'msg': message});
}
static void e(String tag, String message) {
perform.invokeMethod('logE', {'tag': tag, 'msg': message});
}
}
可以看到,代码很简单,初始化一个MethodChannel对象,然后去调用invokeMethod方法,传入参数即可
android端
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(),CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
String tag = methodCall.argument("tag");
String msg = methodCall.argument("msg");
switch (methodCall.method) {
case "logV":
Log.v(tag,msg);
break;
case "logD":
Log.d(tag,msg);
break;
case "logI":
Log.i(tag,msg);
break;
case "logW":
Log.w(tag,msg);
break;
case "logE":
Log.e(tag,msg);
break;
default:
Log.d(tag,msg);
break;
}
}
});
}
这里也是创建一个MethodCallHandler对象,在回调中收到MethodCall对象,取出对应的method和arguments,这里判断method来调用android本身的log方法即可。
例子2:android推送消息到flutter
因为现在其实大部分都是flutter和native原生开发,所以有很多flutter需要主动去推送消息给native层,native层就可以创建EventChannel来监听与flutter的状态,再通过EventSink对象回复消息obj
android端
new EventChannel(getFlutterView(), "com.flutter/notify").setStreamHandler(
new EventChannel.StreamHandler() {
private TokenReceiver tokenReceiver;
@Override
public void onListen(Object args, final EventChannel.EventSink events) {
Log.e("tag", "adding listener");
events.success("data callback");
}
@Override
public void onCancel(Object args) {
Log.e("tag", "cancelling listener");
}
}
);
flutter
static const EventChannel eventChannel = EventChannel('com.flutter/notify');
@override
void initState() {
// TODO: implement initState
super.initState();
//初始化监听
eventChannel.receiveBroadcastStream().listen(_onDataBack, onError: _onError);
}
void _onError(Object error){
}
void _onDataBack(String callback) {
print(callback)
}
代码也很简单,创建相同Channel名字的EventChannel,监听到数据做相应的逻辑即可