Flutter如何和Native通信-Android视角,如何快速的开发一个完整的直播app

96 阅读4分钟

if (batteryLevel != -1) { result.success(batteryLevel); } else { result.error("UNAVAILABLE", "Battery level not available.", null); } } else { result.notImplemented(); } }

onMethodCall有两个入参,MethodCall里包含要调用的方法名称和参数。Result是给Flutter的返回值。方法名是两端协商好的。通过if语句判断MethodCall.method来区分不同的方法,在我们的例子里面我们只会处理名为“getBatteryLevel”的调用。在调用本地方法获取到电量以后通过result.success(batteryLevel)调用把电量值返回给Flutter。 Native端的代码就完成了。是不是很简单?

MethodChannel-Flutter 端

接下来看Flutter端代码怎么写: 首先在 State中创建Flutter端的MethodChannel

import 'dart:async';

import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; ... class _MyHomePageState extends State { static const platform = const MethodChannel('samples.flutter.io/battery');

// Get battery level. }

channel的名称要和Native端的一致。 然后是通过MethodChannel调用的代码

String _batteryLevel = 'Unknown battery level.';

Future _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '{e.message}'."; }

setState(() { _batteryLevel = batteryLevel; }); }

final int result = await platform.invokeMethod('getBatteryLevel');这行代码就是通过通道来调用Native方法了。注意这里的await关键字。前面我们说过MethodChannel是异步的,所以这里必须要使用await关键字。 在上面Native代码中我们把获取到的电量通过result.success(batteryLevel);返回给Flutter。这里await表达式执行完成以后电量就直接赋值给result变量了。剩下的就是怎么展示的问题了,就不再细说了,具体可以去看代码。

需要注意的是,这里我们只介绍了从Flutter调用Native方法,其实通过MethodChannel,Native也能调用Flutter的方法,这是一个双向的通道

举个例子,我们想从Native端请求Flutter端的一个getName方法获取一个字符串。在Flutter端你需要给MethodChannel设置一个MethodCallHandler

_channel.setMethodCallHandler(platformCallHandler);

Future platformCallHandler(MethodCall call) async { switch (call.method) { case "getName": return "Hello from Flutter"; break; } }

在Native端,只需要让对应的的channel调用invokeMethod就行了

channel.invokeMethod("getName", null, new MethodChannel.Result() { @Override public void success(Object o) { // 这里就会输出 "Hello from Flutter" Log.i("debug", o.toString()); } @Override public void error(String s, String s1, Object o) { } @Override public void notImplemented() { } });

至此,MethodChannel的用法就介绍完了。可以发现,通过MethodChannelNative和Flutter方法互相调用还是蛮直接的。这里只是做了个大概的介绍,具体细节和一些复杂用法还有待大家的探索。

MethodChannel提供了方法调用的通道,那如果Native有数据流需要传送给Flutter该怎么办呢?这时候就要用到EventChannel了。

EventChannel

EventChannel的使用我们也以官方获取电池电量的demo为例,手机的电池状态是不停变化的。我们要把这样的电池状态变化由Native及时通过EventChannel来告诉Flutter。这种情况用之前讲的MethodChannel办法是不行的,这意味着Flutter需要用轮询的方式不停调用getBatteryLevel来获取当前电量,显然是不正确的做法。而用EventChannel的方式,则是将当前电池状态"推送"给Flutter.

EventChannel - Native端

先看我们熟悉的Native端怎么来创建EventChannel, 还是在MainActivity.onCreate中,我们加入如下代码:

new EventChannel(getFlutterView(), "samples.flutter.io/charging").setStreamHandler( new StreamHandler() { // 接收电池广播的BroadcastReceiver。 private BroadcastReceiver chargingStateChangeReceiver; @Override // 这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体。 public void onListen(Object arguments, EventSink events) { chargingStateChangeReceiver = createChargingStateChangeReceiver(events); registerReceiver( chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); }

@Override public void onCancel(Object arguments) { // 对面不再接收 unregisterReceiver(chargingStateChangeReceiver); chargingStateChangeReceiver = null; } } );

MethodChannel类似,我们也是直接new一个EventChannel实例,并给它设置了一个StreamHandler类型的回调。其中onCancel代表对面不再接收,这里我们应该做一些clean up的事情。而 onListen则代表通道已经建好,Native可以发送数据了。注意onListen里带的EventSink这个参数,后续Native发送数据都是经过EventSink的。看代码:

private BroadcastReceiver createChargingStateChangeReceiver(final EventSink events) { return new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);

if (status == BatteryManager.BATTERY_STATUS_UNKNOWN) { events.error("UNAVAILABLE", "Charging status unavailable", null); } else { boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL; // 把电池状态发给Flutter events.success(isCharging ? "charging" : "discharging"); } } }; }

onReceive函数内,系统发来电池状态广播以后,在Native这里转化为约定好的字符串,然后通过调用events.success();发送给Flutter。Native端的代码就是这样,接下来看Flutter端。

EventChannel - Flutter端

首先还是在State内创建EventChannel

static const EventChannel eventChannel = const EventChannel('samples.flutter.io/charging');

然后在initState的时候打开这个channel:

@override void initState() { super.initState(); eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); }

收到event以后的处理是在_onEvent函数里:

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

上述【高清技术脑图】以及【配套的架构技术PDF】点击:Android架构视频+BAT面试专题PDF+学习笔记,或者私信回复【技能提升】即可获取!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!