上期文章釋出之後,收到了很多朋友的關注,大家認為彈幕庫能在鴻蒙系統上跑起來非常的炫酷。但同時也有一些朋友問我,像這樣的鴻蒙第三方元件是如何遷移過來的。本期,我們將以彈幕庫為例,讓大家瞭解開源三方件是如何從安卓遷移到鴻蒙的!看完本篇內容,你不僅能夠明白"我們是如何遷移彈幕庫"的,還可以自己嘗試遷移感興趣的安卓開源三方件!
本次的內容包含三個部分,主要為大家講解:開源三方件遷移的本質是什麼、如何完成開源三方件的遷移。
1、 本質
三方件是一個向下使用安卓/鴻蒙的SDK方法,完成特定功能,向上為使用者提供統一的介面,供使用者呼叫的中介軟體。
想將一個安卓的三方件遷移至鴻蒙,要做的是:向上的介面保持不變(功能輸出和介面相同,方便使用者呼叫),向下呼叫的方法由安卓轉為鴻蒙,也就是從使用安卓的底層SDK提供的方法變為使用鴻蒙的底層SDK提供的方法。下圖以彈幕庫為例子解釋了這個過程:
圖1:彈幕庫元件遷移示意圖
原始彈幕庫元件版本(https://github.com/bilibili/DanmakuFlameMaster)中,我們點開其中任意幾個檔案,檢視其import資訊:
圖2:DrawHandler.java
可以看到,檔案中使用了大量的"import android.xxxx"的包名,表明元件包含了大量安卓自身的API呼叫,來實現特定功能,因此我們要做的是透過呼叫鴻蒙的API來實現相同的功能,由於安卓和鴻蒙底層架構及通訊機制等各方面的不同,所以此處並不是簡單地逐一替換關係。
2、 方法
在實際的遷移過程中,安卓和鴻蒙的包名、類名和方法名都可能會不同。根據遷移的難易程度,可以分為以下四種情況。
1. 包名不同,類名相同
有一些比較簡單的類,它在安卓和鴻蒙中僅僅是包名發生了變化,類名、介面和方法沒有變化,像這樣的類,我們只要在檔案中進行import後的包名替換即可,如下圖所示。
圖3: 原始碼示例
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:安卓實現自定義繪製能力
鴻蒙:
圖10:鴻蒙實現自定義繪製能力