鴻蒙開源第三方組件-B站開源彈幕庫引擎的遷移(下)
前言
本期,我們將以彈幕庫為例,讓大家了解開源三方件是如何從安卓遷移到鴻蒙的!
看完本篇內容,你不僅能夠明白"我們是如何遷移彈幕庫"的,還可以自己嘗試遷移感興趣的安卓開源三方件!
本次的內容包含兩個部分,主要為大家講解:開源三方件遷移的本質是什么、如何完成開源三方件的遷移。
1、本質
三方件是一個向下使用安卓/鴻蒙的SDK方法,完成特定功能,向上為用戶提供統一的接口,供用戶調用的中間件。
想將一個安卓的三方件遷移至鴻蒙,要做的是:向上的接口保持不變(功能輸出和接口相同,方便用戶調用),向下調用的方法由安卓轉為鴻蒙,也就是從使用安卓的底層SDK提供的方法變為使用鴻蒙的底層SDK提供的方法。下圖以彈幕庫為例子解釋了這個過程:
圖1:彈幕庫組件遷移示意圖
原始彈幕庫組件版本(https://github.com/bilibili/DanmakuFlameMaster)中,我們點開其中任意幾個文件,查看其import信息:
圖2:DrawHandler.java
可以看到,文件中使用了大量的"import android.xxxx"的包名,表明組件包含了大量安卓自身的API調用,來實現特定功能,因此我們要做的是通過調用鴻蒙的API來實現相同的功能,由于安卓和鴻蒙底層架構及通信機制等各方面的不同,所以此處并不是簡單地逐一替換關系。
2、方法
在實際的遷移過程中,安卓和鴻蒙的包名、類名和方法名都可能會不同。根據遷移的難易程度,可以分為以下四種情況。
1. 包名不同,類名相同
有一些比較簡單的類,它在安卓和鴻蒙中僅僅是包名發生了變化,類名、接口和方法沒有變化,像這樣的類,我們只要在文件中進行import后的包名替換即可,如下圖所示。
2. 類名不同,方法名相同
有一些類,它在安卓和鴻蒙中包名和類名都發生了變化,接口沒有變化,如下圖所示。
圖4:源碼示例
此時需要翻閱安卓和鴻蒙的開發文檔,以未變化的方法名為線索進行查找,對同功能的類進行匹配。
安卓:
https://developer.android.google.cn/reference/packages
鴻蒙:
https://developer.harmonyos.com/cn/docs/documentation/doc-references/overview-0000001054518434
像上面說的兩種簡單情況,在實際的遷移過程中幾乎是不會出現的,在鴻蒙系統中也只有很少一部分基礎庫所提供的接口是與安卓相似的,其他部分的庫與安卓相差甚遠。
3. 包名、類名和方法完全不同
此時,對于安卓中調用的接口,無法直接在鴻蒙中找到與之對應的。需要我們具有一定的源碼閱讀能力,充分理解安卓接口的功能實現和模塊劃分(媒體、權限、視圖...),再去鴻蒙相應的模塊查找與之相似的使用方法。
圖五:源碼示例
這里就是一個典型的例子,注釋方法為安卓方法,下面方法是鴻蒙方法。可以看到在RECT(Class:RectFloat)這個變量的初始化中就出現了不一樣的使用方式。
4. 功能重寫
前三種方法,接口在安卓和鴻蒙間存在對應關系,我們只需要理解、查找和匹配。在功能實現方式完全不同的情況下,需要我們具有一定的代碼閱讀能力和重寫能力,在鴻蒙中對相應功能進行重寫。以彈幕庫為例:
---多線程通信:
安卓和鴻蒙的多線程通信機制類似,但是使用方法相差較大。
解決方法:功能重寫。
圖6:安卓中的多線程通信邏輯
圖7:鴻蒙中的多線程通信邏輯
可以看到兩個版本的多線程通信的大體邏輯都是相同的,兩個Thread想要進行通信,都需要四個步驟:
1.通信發起方需要構建(或實例化)一個結構體(或類)來進行事件的傳遞(并攜帶信息本身)。
2.這個攜帶著信息的結構化對象到了信息接收方后,會首先進入一個消息隊列進行等待處理。
3.當結構化對象被從隊列中取出后,會進入消息接收方的信息處理邏輯。
4.處理完成后消息接收方會生成一個反饋(回調),將處理結果反饋給消息發送方。
但是我們可以細心觀察一下,安卓和鴻蒙的處理細節是有很大差異的。在安卓上使用這個機制的時候,需要先new一個HandlerThread,然后new一個looper,接著將他們綁定在一起,使用Thread.start才能讓跑起來,實現消息隊列發送及取出消息處理的功能。在鴻蒙上則不用如此麻煩,只需要new一個eventrunner就可以實現同樣的功能,如下圖所示。
圖8:源碼示例
---UI部分
由于鴻蒙UI的構建方式和安卓存在很多差異,導致無法直接通過替換接口的方式來實現與安卓相對應的UI能力,這就需要進一步將對應的功能基于鴻蒙的構建方式進行重寫。
解決方法:功能重寫
以OHOSP/AOSP自定義繪制能力對比為例:
圖9:OHOSP/AOSP自定義繪制能力對比圖
安卓在繪制時,直接調用draw()方法,將canvas繪制到view上,鴻蒙則需對當前的component添加drawtask,重寫drawtask里的ondraw方法,完成對canvas的繪制。
安卓實現如下:
圖10:安卓實現自定義繪制能力
鴻蒙:
圖11:鴻蒙實現自定義繪制能力