内容简介:前不久开源了用Flutter开发的一个音视频类App客户端,欢迎大家star, fork。:warning: 本篇博客涉及的源码全部开源在Github,地址:
前不久开源了用Flutter开发的一个音视频类App客户端,欢迎大家star, fork。
:warning: 项目地址: github.com/songxiaolia…
:warning: 本篇博客涉及的源码全部开源在Github,地址: github.com/songxiaolia…
目前现有的跨平台开发解决方案基本分为两种开发模式:
(1)纯跨平台语言开发模式
(2)Native + Hybrid 混合开发模式
在纯跨平台开发方案带来的高效开发效率的同时,混合开发也为原生App提供了更方便更快捷的功能实现。例如,React Native 热更新,跨平台双端UI视图等。
了解React Native的朋友,对 Android & RN 的开发模式肯定不会陌生,在之前的文章中,我也介绍了如何将RN实践在Android原生App中,详细内容大家可以查看 《Android 集成 React Native、原生视图加载RN组件模块分析》 。本篇博客将围绕跨平台开发框架 Flutter,详细介绍如何集成在现有Android原生项目,以及双端的通信实现流程。
效果图
一、Android 集成 Flutter 实现流程
闲鱼、头条 在 Android 集成 Flutter 模块都有自己的实现方案:闲鱼团队方案 &头条团队方案
我们以 官方方案 方式为主。
1)创建 flutter module 模块
官方提供了如下命令,用来创建 flutter module:
flutter create -t module flutter_module (module名称)复制代码
2)将 flutter module 模块添加到当前项目
打开项目根目录的 settings.gradle 文件,添加如下代码片段:
setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir.parentFile, "flutter_in_android/.android/include_flutter.groovy" ))复制代码
打开 app / build.gradle 文件,在 dependencies 下添加 flutter 依赖:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' ...... implementation project(':flutter') }复制代码
以上配置完成后,Flutter就已经集成在当前Android工程项目中了。
二、Flutter 视图界面展示
Flutter的视图展示有两种实现方式:
(1)创建 FlutterView 视图组件,以 View 的方式添加到当前原生视图布局
官方依赖库中提供了 createView 的方法,方便开发者快速创建 Flutter 视图组件,并嵌入在当前原生布局:
/** * 此 Activity 中向 Flutter 端发送消息 * create by Songlcy 2019-02-15 */ public class FlutterContainerActy extends AppCompatActivity { private ViewGroup.LayoutParams layoutParams; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flutter); // 1. 通过Flutter.createView创建FlutterView组件方式 FlutterView flutterView = Flutter.createView(this, getLifecycle(), "flutterView"); layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); // 2. 将Flutter 视图添加到原生布局中 addContentView(flutterView, layoutParams); } }复制代码
上述代码中,我们通过 Flutter.createView 创建 Flutter 视图组件 FlutterView ,createView方法接收三个参数
@NonNull final Activity activity: Activity实例 @NonNull final Lifecycle lifecycle: 定义具有Android生命周期的对象 final String initialRoute: 初始化的视图路由名称复制代码
所以我们可以根据 initialRoute 来动态加载不同的 Flutter 视图组件:
import 'dart:ui'; // 引入后可以使用window对象 @override Widget build(BuildContext context) { switch(window.defaultRouteName) { case "flutterView": return Scaffold(...); ...... default: return Center( child: Text('Unknown route: $route', textDirection: TextDirection.ltr), ); } }复制代码
(2)启动 FlutterActivity 界面
在很多场景下,我们需要从原生界面跳转到Flutter视图界面,所以我们可以直接启动FlutterActivity来实现:
Intent intent = new Intent(MainActivity.this, FlutterActy.class);startActivity(intent);复制代码
三、Android 与 Flutter 通信方式
React Native跨平台开发框架是通过 RCTBatchedBridge 实现 js 与 Native 的交互,Flutter与Native的通信机制与RN的实现比较相似,只是没有了Bridge的桥接层,通过Channel直接与原生交互。官方在Channel通信的实现上同样采用了以字符串为唯一协议的方式,来同时构建通信交互信号。实现的具体方式和RN也同样类似,Native | Flutter 端实现监听回调,注册即可。
(1)MethodChannel
使用场景:Flutter端向Native端发送通知
实现方式:
Native端
new MethodChannel(getFlutterView(), "com.xxx").setMethodCallHandler(new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) { // methodCall.method 对应 Flutter端invokeMethod方法的第一个参数 if(methodCall.method.equals("123")) { // 获取Flutter传递的参数 String msg = methodCall.<String>argument("msg"); // 回传给Flutter result.success(msg); } } });复制代码
上述代码中我们创建了MethodChannel实例,并调用 setMethodCallHandler 注册监听回调。从源码中,可以看到MethodChannel构造函数接收两个参数
public MethodChannel(BinaryMessenger messenger, String name) { this(messenger, name, StandardMethodCodec.INSTANCE); } public MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec) { ...... }复制代码
name 就是双发通信的唯一标识,我们可以简单理解为钥匙即可。
MethodCodec有两种实现:
- JSONMethodCodec
JSONMethodCodec的编解码依赖于JSONMessageCodec,当其在编码MethodCall时,会先将MethodCall转化为字典{"method":method,"args":args}。其在编码调用结果时,会将其转化为一个数组,调用成功为[result],调用失败为[code,message,detail]。再使用JSONMessageCodec将字典或数组转化为二进制数据。
- StandardMethodCodec
MethodCodec的默认实现,StandardMethodCodec的编解码依赖于StandardMessageCodec,当其编码MethodCall时,会将method和args依次使用StandardMessageCodec编码,写入二进制数据容器。其在编码方法的调用结果时,若调用成功,会先向二进制数据容器写入数值0(代表调用成功),再写入StandardMessageCodec编码后的result。而调用失败,则先向容器写入数据1(代表调用失败),再依次写入StandardMessageCodec编码后的code,message和detail。
Flutter端
import 'package:flutter/services.dart'; static const methodPlugin = const MethodChannel('com.xxx'); String callbackResult = await methodPlugin.invokeMethod('123', { "msg": "456" });复制代码
在Flutter同样需要创建MethodChannel实例,并将通信钥匙作为参数传入,要与原生端保持一致。然后调用invokeMethod方法向原生端发送通信请求。第一个参数表示要调用原生端的哪个方法,第二个参数为 可选参数 ,即传递给Native端的数据参数。
(2)EventChannel
使用场景:Native端向Flutter端发送通知
实现方式:
Native端
new EventChannel(getFlutterView(), "com.xxx").setStreamHandler(new EventChannel.StreamHandler() { @Override public void onListen(Object o, EventChannel.EventSink eventSink) { eventSink.success("msg"); } @Override public void onCancel(Object o) { // 做一些注销操作 } });复制代码
和 MethodChannel 类似,EventChannel 也是通过 new 创建对象实例,并设置 StreamHandler 类型的监听回调。其中 onCancel 代表对面不再接收,这里我们可以做注销的逻辑操作。onListen 代表通信已经建立完毕,Native可以向Flutter发送数据。onListen 方法中携带了 EventSink 参数,后续Native发送数据都是经过 EventSink 的 success、error 方法。
Flutter端
import 'package:flutter/services.dart'; static const eventPlugin = const EventChannel('com.xxx'); @override void initState() { super.initState(); _streamSubscription = eventPlugin.receiveBroadcastStream() .listen(_onData, onError: _onError, onDone: _onDone, cancelOnError: true); } void _onData(Object event) { // 接收数据 setState(() { eventVal = event; }); } void _onError(Object error) { // 发生错误时被回调 setState((){ eventVal = "错误"; }); } void _onDone() { //结束时调用 } @override void dispose() { super.dispose(); if(_streamSubscription != null) { _streamSubscription.cancel(); } }复制代码
同样与 MethodChannel 类似,首先是创建 EventChannel 实例,然后在 initState 生命周期中调用 receiveBroadcastStream方法的listen。listen 返回的是 StreamSubscription 对象。此处有点类似Android中的BroadcastReceiver广播。listen方法源码如下:
StreamSubscription<T> listen(void onData(T event), {Function onError, void onDone(), bool cancelOnError});复制代码
可以看到,onData 为必需参数,onError、onDone、cancelOnError 为可选。顾名思义,onData 即为收到原生端发送数据的回调,onError为接收数据失败,onDone为接收数据结束,cancelOnError是一个bool类型参数,标识在发生错误时,时候自动取消通信。以上即可实现Native端向Flutter发送通知。
总结
Platform Channel 作为原生端与 Flutter 端建立通信渠道的方式,在混合开发模式中起到了至关重要的作用,很多地方都会涉及,例如编写 Plugin 等等。不仅能够帮助我们更深入的了解 Flutter 与 Native 之间的交互流程,在性能优化、问题分析上都可以得到延伸。
以上所述就是小编给大家介绍的《Android 集成 Flutter 及通信交互详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 利用expect命令实现Shell自动化交互的方法详解
- iOS 12 人机交互指南:交互(User Interaction)
- 生活NLP云服务“玩秘”站稳人机交互2.0语音交互场景
- asyncio之子进程交互
- 以太坊交互工具
- 学习 PixiJS — 交互工具
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
黑客大曝光
Joel Scambray、Vincent Liu、Caleb Sima / 姚军 / 机械工业出版社华章公司 / 2011-10 / 65.00元
在网络技术和电子商务飞速发展的今天,Web应用安全面临着前所未有的挑战。所有安全技术人员有必要掌握当今黑客们的武器和思维过程,保护Web应用免遭恶意攻击。本书由美国公认的安全专家和精神领袖打造,对上一版做了完全的更新,覆盖新的网络渗透方法和对策,介绍如何增强验证和授权、弥补Firefox和IE中的漏洞、加强对注入攻击的防御以及加固Web 2.0安全,还介绍了如何将安全技术整合在Web开发以及更广泛......一起来看看 《黑客大曝光》 这本书的介绍吧!