博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter与Android混合开发及Platform Channel的使用
阅读量:5743 次
发布时间:2019-06-18

本文共 6487 字,大约阅读时间需要 21 分钟。

  1. 相对于单独开发Flutter应用,混合开发对于线上项目更具有实际意义,可以把风险控制到最低,也可以进行实战上线。所以介绍 集成已有项目

  2. 混合开发涉及原生Native和Flutter进行通信传输,还有插件编写,所以介绍 两端通信Flutter Platform Channel的使用

集成已有项目

 |  | 

采用官方的实现方式,对个人和小团队相对简单易用,并没有实践闲鱼和头条等大项目的方式。个中利弊上述推荐均有提到。

开始

  1. 在已有项目根目录运行命令

flutter create -t module my_flutter

不一定非在项目下创建,兼顾ios,位置路径寻址对即可

2.在项目的settings.gradle 文件添加如下代码

// MyApp/settings.gradleinclude ':app'                                     // assumed existing contentsetBinding(new Binding([gradle: this]))                                 // newevaluate(new File(                                                      // new  settingsDir.parentFile,                                               // new  'my_flutter/.android/include_flutter.groovy'                          // new))                                                                      // new
Binding飘红不予理会,强迫症的不用导包
'my_flutter/.android/include_flutter.groovy'为my_flutter文件路径,报错找不到可写项目全路径'ChannelFlutterAndroid/my_flutter/.android/include_flutter.groovy'
3.在运行模块app的build.gradle添加依赖
// MyApp/app/build.gradledependencies {    implementation project(':flutter')}

4.在原生Android端创建并添加flutterView

val flutterView = Flutter.createView(this, lifecycle, "route1") val layoutParams = FrameLayout.LayoutParams(-1, -1) addContentView(flutterView, layoutParams)

5.在Flutter端入口操作

void main() => runApp(_widgetForRoute(window.defaultRouteName));Widget _widgetForRoute(String route) {  switch (route) {    case 'route1':      return SomeWidget(...);    default:      return Center(        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),      );  }}
  1. 至此,集成完毕

两端通信Flutter Platform Channel的使用

本文主要是介绍使用方式,

Flutter提供 MethodChannelEventChannelBasicMessageChannel 三种方式

  1. 类似注册监听,发送的模式 原则
  2. 使用顺序:先注册,后发送,否则接收不到。尤其使用 MethodChannelEventChannel 不符合该原则会抛出异常,BasicMessageChannel方式只是收不到消息

方式一 MethodChannel

应用场景:Flutter端 调用 Native端

Flutter端代码:

var result = await MethodChannel("com.simple.channelflutterandroid/method",                       StandardMethodCodec())                      .invokeMethod("toast", {
"msg": msg})

Android端代码:

MethodChannel(flutterView, "com.simple.channelflutterandroid/method",              StandardMethodCodec.INSTANCE)             .setMethodCallHandler { methodCall, result ->        when (methodCall.method) {             "toast" -> {                //调用传来的参数"msg"对应的值                val msg = methodCall.argument
("msg") //调用本地Toast的方法 Toast.makeText(cxt, msg, Toast.LENGTH_SHORT).show() //回调给客户端 result.success("native android toast success") } "other" -> { // ... } else -> { // ... } } }

 

  • 注意点1:两端需要对应一致的点

    方法名称:com.simple.channelflutterandroid/method,可以不采取包名,对应一致即可,不同的方式最好不要重复
    传参key:"msg"

  • 注意点2:以下为Flutter为例,Android同理

    StandardMethodCodec() 非必传,默认是 StandardMethodCodec(),是一种消息编解码器

    对于 MethodChannelEventChannel 两种方式,有两种编解码器,均实现自MethodCodec ,分别为 StandardMethodCodecJsonMethodCodec

    对于 BasicMessageChannel 方式,有四种编解码器,均实现自MessageCodec ,分别为 StandardMessageCodecJSONMessageCodecStringCodecBinaryCodec

  • 注意点3:setMethodCallHandler(),针对三种方式一一对应,属于监听

    MethodChannel - setMethodCallHandler()
    EventChannel - setStreamHandler()
    BasicMessageChannel - setMessageHandler()
    其中setStreamHandler()方式稍微特殊,具体查看上面提的闲鱼文章

  • 注意点4:FlutterView 实现 BinaryMessenger 接口

以上,以下两种方法不再赘述

方式二 EventChannel

应用场景:Native端 调用 Flutter端,方式稍微特殊

Flutter端代码:属于接收方

EventChannel("com.simple.channelflutterandroid/event")           .receiveBroadcastStream()           .listen((event){                   print("It is Flutter -  receiveBroadcastStream $event");   })

注意 receiveBroadcastStream

Android端代码:属于发送方

EventChannel(flutterView, "com.simple.channelflutterandroid/event")         .setStreamHandler(object : EventChannel.StreamHandler {               override fun onListen(o: Any?, eventSink: EventChannel.EventSink) {                     eventSink.success("我是发送Native的消息")               }               override fun onCancel(o: Any?) {                       // ...               }   })

方式三 BasicMessageChannel

应用场景:互相调用

两种使用方式,创建方式和格式不一样

第一种

Flutter端

_basicMessageChannel = BasicMessageChannel("com.simple.channelflutterandroid/basic",                                                 StringCodec())    // 发送消息    _basicMessageChannel.send("我是Flutter发送的消息");    // 接收消息    _basicMessageChannel.setMessageHandler((str){        print("It is Flutter -  receive str");    });

Android端

val basicMessageChannel = BasicMessageChannel
(flutterView, "com.simple.channelflutterandroid/basic", StringCodec.INSTANCE) // 发送消息 basicMessageChannel.send("我是Native发送的消息") // 接收消息 basicMessageChannel.setMessageHandler { o, reply -> println("It is Native - setMessageHandler $o") reply.reply("It is reply from native") }

其中StringCodec(),四种方式可选

第二种

Flutter端

static const BASIC_BINARY_NAME = "com.simple.channelflutterandroid/basic/binary";   // 发送消息   val res = await BinaryMessages.send(BASIC_BINARY_NAME, ByteData(256))   // 接收消息   BinaryMessages.setMessageHandler(BASIC_BINARY_NAME, (byteData){       println("It is Flutter - setMessageHandler $byteData")   });

Android端

const val BASIC_BINARY_NAME = "com.simple.channelflutterandroid/basic/binary"   // 发送消息   flutterView.send(BASIC_BINARY_NAME,ByteBuffer.allocate(256));   // 接收消息   flutterView.setMessageHandler(BASIC_BINARY_NAME) { byteBuffer, binaryReply ->       println("It is Native - setMessageHandler $byteBuffer")       binaryReply.reply(ByteBuffer.allocate(256))   }

此组合可以进行图片的传递

help 在操作中使用此方式传输数据总报错,所以只传了默认ByteBuffer。还是姿势不对???目前未发现,求大神指教

如有错误之处,万望各位指出!谢谢

其他

  1. Native端接收方收到消息后都能进行回传信息,在Flutter进行异步接收
    MethodChannel:result.success("我是回传信息");
    EventChannel:eventSink.success("我是回传信息");
    BasicMessageChannel:binaryReply.reply(-);- Flutter端:ByteData;Android端:ByteBuffer

Q&A

以上均为理想情况,过程中还是存在许多问题,以下提供参考

Q:使用命令行flutter create创建的project或者module,文件android/ios为隐藏打点开头的.android/.ios文件

A:所以有的时候会出现问题,寻找不到文件的情况

Q: flutter create module 和project的区别

A: ?? 目前没发现

Q:couldn't locate lint-gradle-api-26.1.2.jar for flutter project

A:

Q: Could not resolve all files for configuration ':app:androidApis'.

Failed to transform file 'android.jar' to match attributes {artifactType=android-mockable-jar, returnDefaultValues=false} using transform MockableJarTransform
A:

Q: Flutter Error: Navigator operation requested with a context that does not include a Navigator

A:

转载地址:http://fzizx.baihongyu.com/

你可能感兴趣的文章
tmux不自动加载配置文件.tmux.conf
查看>>
[MOSEK] Stupid things when using mosek
查看>>
程序实例---栈的顺序实现和链式实现
查看>>
服务的使用
查看>>
Oracle 用户与模式
查看>>
MairDB 初始数据库与表 (二)
查看>>
拥在怀里
查看>>
chm文件打开,有目录无内容
查看>>
whereis、find、which、locate的区别
查看>>
一点不懂到小白的linux系统运维经历分享
查看>>
桌面支持--打不开网页上的pdf附件解决办法(ie-tools-compatibility)
查看>>
nagios监控windows 改了NSclient++默认端口 注意事项
查看>>
干货 | JAVA代码引起的NATIVE野指针问题(上)
查看>>
POI getDataFormat() 格式对照
查看>>
Python 中的进程、线程、协程、同步、异步、回调
查看>>
好的产品原型具有哪些特点?
查看>>
实现java导出文件弹出下载框让用户选择路径
查看>>
刨根问底--技术--jsoup登陆网站
查看>>
OSChina 五一劳动节乱弹 ——女孩子晚上不要出门,发生了这样的事情
查看>>
Spring--通过注解来配置bean
查看>>