HarmonyOS 分布式协同演奏技术实现路线(Java)
一、写在前面的话
分布式能力是鸿蒙的一大亮点,不管是分布式数据库,还是分布式文件管理,抑或是分布式任务流转,都给我们日常的使用习惯带来很大的变革。很多时候我就在想,我们还能怎样应用分布式系统呢?百思不得其解之时,爱因斯坦的小提琴就莫名其妙地浮现在了脑海里。音乐!一个好的乐队、好的乐团,不正是由一个个小的部分组成的吗?于是,自由乐队就孕育而出了。
本文将重点讲述下自由乐队分布式协同演奏的技术实现路线,重点讲的是思路,讲得不好的地方还请大家多多包涵。
二、路线一
采用监听数据库的方法实现组网间设备的协同演奏。
主要流程如上图,核心就是分布式状态数据库和分布式音乐演奏数据库,通过监听这两个数据库实现组网间设备的组队和协同演奏功能。分布式状态数据库用于组队信息的传输,分布式协同演奏数据库用于乐器模拟按键信息的传输。
1、分布式音乐演奏数据库的初始化
如下图,我们软件初始化的时候就会创建属于该设备的 DeviceKvStore,并对其进行监听。
同时,我们在 DataAbility 里有个 deviceKvStores 用来保存 deviceId 和 DeviceKvStore 的对应关系。
2、判断是否为本地端
如下图,我们采用通过 intent 携带的关键字来判断是否为本地端。
本地端调起协同端时,写入该关键字:
3、点击事件的处理
如下图,当监听到点击事件发生的时候,统一调用 DataAbility.clickSound(),为防止阻塞,我们使用异步调用的方式。
而 DataAbility.clickSound()则会通过 DeviceId 获取到 DeviceKvStore,同时将按键点击事件的 mSrc(即相应按键的 ID)写入。
4、DeviceKvStore 数据库的监听
如下图,首先会判断是否为本地端,若为本地端则处理点击事件。处理点击事件的核心就是获取到点击按键的 mSrc,首先通过 notification.getDeviceId()获取到 DeviceId,然后通过 DeviceId 去获取响应的 DeviceKvStore,然后通过 key 来拿到 mSrc,进而调用 DataAbility.playClip()。DataAbility.playClip()就是模拟乐器演奏的相关函数。
5、分布式状态数据库的初始化
6、分布式状态数据库的监听
核心就是获取此时退出队伍设备的 DeviceId,若当前设备为本地端,则停止对该设备进行监听,同时弹出该设备退出队伍的提示;若当前设备为协同端,同时发起退出设备的 DeviceId 为当前队伍的本地端,则表示该队伍已解散,当前设备变为本地端,同时弹出队伍已解散的提示。
值得一提的是,分布式状态数据库是所有设备初始化的时候都通过 DataAbility.STATE_KEY 来监听同一个分布式状态数据库 DeviceKvStore,而分布式音乐演奏数据库则是每个设备都会根据自己唯一的 DataAbility.storeId 来创建分布式音乐演奏数据库 DeviceKvStore,也就是说会有多个分布式音乐演奏数据库。
因此,我们是在 DataAbility 里通过 deviceKvStores 来储存 DeviceId 和 DeviceKvStore 的对应关系。组队的实质就是实现对相应分布式音乐演奏数据库的监听。多个 DeviceKvStore 就能够实例化多个 KvStoreObserver 来对多个数据库进行监听,并行进行处理,减少并发带来的影响,降低协同演奏的延时。
7、协同演奏模拟乐器
协同端和本地端一样,当监听到点击事件的时候,也是调用 DataAbility.clickSound()。同样在 DataAbility.clickSound()里通过 DeviceId 获取 DeviceKvStore,然后将按键点击事件的 mSrc 写入相应的 DeviceKvStore 分布式数据库。
不同的是协同端的 KvStoreObserver 虽然监听到了数据变化,但是判断当前设备为协同端,则不会去进行模拟乐器演奏的播放。而此时,组队本地端也同时监听到了数据变化,进而去进行模拟乐器演奏的播放。
三、路线二
我们想到的第二种实现分布式协同演奏的方法就是类似于 Codelabs 里面的分布式游戏手柄的写法(链接在文末),本地端调起协同端的时候通过 IAbilityConnection 进行连接。同时,协同端通过 proxy.senDataToRemote()将按键信息发送给本地端,本地端通过 onRemoteRequest()来处理协同端发来的信息。详细讲解可以参考 Codelabs 里面的代码,同时有一些包也在 Demo 里面封装好了,可以不用重复造轮子。
具体代码实现我之前测试的时候都写好了。BUT,因为太卡了,我们就放弃了这条路线,代码也给回退了。(也可能是我们的水平有限,代码优化得不是很好)我们当时是先写的通过订阅分布式数据库来实现协同演奏的,但是我最开始是只通过订阅一个单板本分布式数据库实现的协同演奏,感觉效果不太理想,就尝试了路线二。尝试了之后发现,路线二还没有之前的延迟小呢,就最终确定了采用路线一,同时后面又对路线一进行了相关的优化,比如采用订阅分布式状态数据库和多个分布式音乐演奏数据库、异步处理点击事件、线程阻塞等等技术来降低延迟,最终实现了至少三个设备(当时手上只有三个设备)可以协同演奏一首曲子的程度。
四、总结
协同演奏的实现路线我们研究了两条,分别是监听数据库和直接建立连接。两者都可以实现功能,但是协同演奏很重要的一点就是延迟,延迟太大就真的只能听个响了。个人觉得,就目前来看,鸿蒙在分布式减少延迟这块还是有很长的路要走的。
评论