一、写在前面的话
分布式能力是鸿蒙的一大亮点,不管是分布式数据库,还是分布式文件管理,抑或是分布式任务流转,都给我们日常的使用习惯带来很大的变革。很多时候我就在想,我们还能怎样应用分布式呢?百思不得其解之时,爱因斯坦的小提琴就莫名其妙地浮现在了脑海里。音乐!一个好的乐队、好的乐团,不正是由一个个小的部分组成的吗?于是,自由乐队就蕴育而出了。
本文将重点讲述下自由乐队分布式协同演奏的技术实现路线,重点讲的是思路,讲的不好的地方还请大家多多包涵。
二、路线一
采用监听数据库的方法实现组网间设备的协同演奏。
主要流程如上图,核心就是分布式状态数据库和分布式音乐演奏数据库,通过监听这两个数据库实现组网间设备的组队和协同演奏功能。分布式状态数据库用于组队信息的传输,分布式协同演奏数据库用于乐器模拟按键信息的传输。
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,因为太卡了,我们就放弃了这条路线,代码也给回退了。(也可能是我们的水平有限,代码优化的不是很好)我们当时是先写的通过订阅分布式数据库来实现协同演奏的,但是我最开始是只通过订阅一个单板本分布式数据库实现的协同演奏,感觉效果不太理想,就尝试了路线二。尝试了之后发现,路线二还没有之前的延迟小呢,就最终确定了采用路线一,同时后面又对路线一进行了相关的优化,比如采用订阅分布式状态数据库和多个分布式音乐演奏数据库、异步处理点击事件、线程阻塞等等技术来降低延迟,最终实现了至少三个设备(当时手上只有三个设备)可以协同演奏一首曲子的程度。
四、总结
协同演奏的实现路线我们研究了两条,分别是监听数据库和直接建立连接。两者都可以实现功能,但是协同演奏很重要的一点就是延迟,延迟太大就真的只能听个响了。个人觉得,就目前来看,鸿蒙在分布式减少延迟这块还是有很长的路要走的。
Codelabs:分布式游戏手柄(Java)。