首頁>科技>

小編在前兩篇中給大家講解了鴻蒙應用開發入門,總體感覺與android比較類似,很容易上手,那麼鴻蒙HarmonyOS到底跟android有什麼不同呢?鴻蒙最大的不同點在於它是為萬物互聯而出生的,而不僅僅是為了手機而生,最核心優勢就是它的分散式開發。那麼到底什麼是鴻蒙分散式?它有什麼不可替代的價值?它又如何開發呢?小編將在本篇為大家一一解密。

首先來看鴻蒙官網一個案例圖吧,這個案例講的是一個使用者用手機打車軟體叫了網約車,然後把手機裝兜裡,抬手在手錶上可以看車輛應答進展,手機與手錶之間的資訊是無縫切換的,如同一個裝置兩個螢幕一樣,這就是分散式的最好體現。所以通俗來講,所謂分散式,就是在不同裝置之間實時協同工作,如同一個大裝置不同模組一樣能緊密配合。這種跨裝置協同能力,與傳統的android系統不一樣,傳統android裝置之間需要多個app約定好協議才能搜尋、發現、配對後聯機工作。而harmonyos是直接在系統層支援了多裝置間的發現、連線,對應用來說只用呼叫簡單的介面,就可以實現分散式執行在多個裝置上進行高效協同。未來科幻電影裡的智慧家居場景,就需要鴻蒙這樣的作業系統才能支撐,這也是鴻蒙能夠彎道超車安卓的一大潛在機遇。

手機手錶協同叫車

好,說了鴻蒙分散式的含義和價值後,我們直接上程式碼,帶領大家來體驗一下如何開發分散式應用吧。在New Project時,選擇News Feature Ability這個模板,這個模板是一個新聞資訊流頁面,包含一個新聞列表頁和一個新聞詳情頁。這個demo的Ability如何佈局、列表List如何用MVC實現等等,由於在上篇電商demo裡已經解析過,這裡就不詳細說了。我們直接找到最核心的分散式程式碼。

建立demo工程

第一步,先看看config.json檔案,這個檔案跟android裡的mainfest.xml一樣,是定義一些ability屬性及所需許可權的,這裡面有三個非常重要的許可權,它表示是否允許本app訪問和監聽其它分散式裝置。

{  "name": "ohos.permission.DISTRIBUTED_DATASYNC"},{  "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"},{  "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"},

第二步,分散式嘛,肯定是要一個裝置連線訪問另一個裝置,在鴻蒙裡,我們可以把本機叫做客戶端,把要連線的目標裝置叫服務端,那麼客戶端與服務端是兩個獨立的程序,如何通訊呢?鴻蒙採用了流行的proxy/stub模式,即代理存根模式。透過IDL(介面定義語言)定義裝置間通訊的介面,然後用工具自動生成對應的proxy和stub檔案,其中proxy執行在客戶端,stub執行在服務端,他們像是中介一樣,連線著客戶端和服務端。

代理和存根

代理框架圖

我們從上面截圖裡可以看到,IDL裡只有一個介面,就是transShare(),它有5個引數,從變數名稱我們大概可以猜到其含義是裝置ID、新聞網址、新聞標題、新聞摘要、新聞封面圖。這個IDL介面的目的是可以讓客戶端裝置把一條新聞資訊同步給服務端裝置。

void tranShare(        String deviceId,        String shareUrl,        String shareTitle,        String shareAbstract,        String shareImg)

我們再看一下根據這個IDL檔案自動生成的proxy/stub檔案程式碼,以proxy為例,我們可以看到它主要是把新聞各個資訊欄位透過data.write()函式序列化,然後把序列化的結果透過remote.sendRequest()方法發給服務端,服務端那邊會透過stub檔案接收這個物件,然後再把它反序列化,從而得到新聞各個資訊欄位。stub程式碼這裡就不貼出來了。

package com.example.myapplication.manager;import ohos.rpc.IRemoteObject;import ohos.rpc.MessageOption;import ohos.rpc.MessageParcel;import ohos.rpc.RemoteException;/** * News demo */public class NewsDemoIDLProxy implements INewsDemoIDL {    private static final String DESCRIPTOR = "com.example.myapplication.INewsDemoIDL";    private static final int COMMAND_TRAN_SHARE = IRemoteObject.MIN_TRANSACTION_ID;    private final IRemoteObject remote;    NewsDemoIDLProxy(IRemoteObject remote) {        this.remote = remote;    }    @Override    public IRemoteObject asObject() {        return remote;    }    @Override    public void tranShare(            String deviceId,            String shareUrl,            String shareTitle,            String shareAbstract,            String shareImg) throws RemoteException {        MessageParcel data = MessageParcel.obtain();        MessageParcel reply = MessageParcel.obtain();        MessageOption option = new MessageOption(MessageOption.TF_SYNC);        data.writeInterfaceToken(DESCRIPTOR);        data.writeString(deviceId);        data.writeString(shareUrl);        data.writeString(shareTitle);        data.writeString(shareAbstract);        data.writeString(shareImg);        try {            remote.sendRequest(COMMAND_TRAN_SHARE, data, reply, option);            reply.readException();        } finally {            data.reclaim();            reply.reclaim();        }    }}

定義好了代理和存根之後,客戶端裝置就可以透過代理連線服務端了。那麼客戶端又該如何發現和選中服務端裝置呢?我們先執行一下demo看看介面,首頁是一個新聞列表頁,點選某條新聞後,是一個新聞詳情頁面,底部右側角上有個分享按鈕,點了後會彈出一個對話方塊(Harmony devices),這個對話方塊本意是要顯示發現的其他鴻蒙裝置,以便將新聞資訊分散式的同步到那些裝置上。由於小編這裡除錯使用的是遠端雲手機,因此沒有辦法真正發現其他鴻蒙裝置,如果是在家裡用真正的手機除錯,旁邊又有其他鴻蒙裝置比如電視的話,那這個對話方塊裡就會顯示鴻蒙裝置列表的。

新聞列表介面

新聞詳情頁

iconShared.setClickedListener(listener -> {    initDevices();    showDeviceList();});

再看看initDevices()是如何做的?透過鴻蒙系統提供的裝置管理API DeviceManager直接可以獲取分散式裝置資訊,這裡返回的是一個List,因為可連線的分散式裝置可能有多個。

private void initDevices() {    if (devices.size() > 0) {        devices.clear();    }    List<ohos.distributedschedule.interwork.DeviceInfo> deviceInfos =            DeviceManager.getDeviceList(ohos.distributedschedule.interwork.DeviceInfo.FLAG_GET_ONLINE_DEVICE);    LogUtil.info("MainAbilityDetailSlice", "deviceInfos size is :" + deviceInfos.size());    devices.addAll(deviceInfos);}

然後再把這些裝置顯示出來,讓使用者選擇需要同步到哪個裝置上去分散式執行?這裡就比較簡單了,把裝置List繫結到一個對話方塊的列表UI裡即可。

private void showDeviceList() {    dialog = new CommonDialog(MainAbilityDetailSlice.this);    dialog.setAutoClosable(true);    dialog.setTitleText("Harmony devices");    dialog.setSize(DIALOG_SIZE_WIDTH, DIALOG_SIZE_HEIGHT);    ListContainer devicesListContainer = new ListContainer(getContext());    DevicesListAdapter devicesListAdapter = new DevicesListAdapter(devices, this);    devicesListContainer.setItemProvider(devicesListAdapter);    devicesListContainer.setItemClickedListener((listContainer, component, position, listener) -> {        dialog.destroy();        startAbilityFA(devices.get(position).getDeviceId());    });    devicesListAdapter.notifyDataChanged();    dialog.setContentCustomComponent(devicesListContainer);    dialog.show();}

仔細看看上面程式碼中,裝置列表的點選事件listener,它呼叫了startAbilityFA()函式,意圖在於當用戶選擇某個裝置時,就開始分散式遷移到對應裝置上去執行。開啟它的程式碼,可以看到第一步是定義一個intent,裡面填入目標裝置deviceID,目標裝置裡要執行的ability(這個案例裡是一個服務SharedService)。然後開始呼叫 connectAbility()函式連線遠端裝置,在連線成功的回撥函數里,就可以拿到遠端裝置的代理,透過IDL介面就可以像操控本地裝置一樣,操控遠端裝置。至此,我們就完成了分散式開發啦。

private void startAbilityFA(String devicesId) {    Intent intent = new Intent();    Operation operation = new Intent.OperationBuilder()            .withDeviceId(devicesId)            .withBundleName(getBundleName())            .withAbilityName("com.example.myapplication.SharedService")            .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)            .build();    intent.setOperation(operation);    boolean connectFlag = connectAbility(intent, new IAbilityConnection() {        @Override        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {            INewsDemoIDL sharedManager = NewsDemoIDLStub.asInterface(iRemoteObject);            try {                sharedManager.tranShare(devicesId, "url", "title", "abstract", "image");            } catch (RemoteException e) {                LogUtil.info("MainAbilityDetailSlice", "connect successful,but have remote exception");            }        }        @Override        public void onAbilityDisconnectDone(ElementName elementName, int i) {            disconnectAbility(this);        }    });    if (connectFlag) {        DialogUtil.toast(this, connectFlag ? "Sharing succeeded!"                : "Sharing failed. Please try again later.", WAIT_TIME);    }}

作為Android開發者,看完鴻蒙核心優勢分散式程式碼後,我們反過來從安卓裡去找類似設計,可以看到與安卓Activity去Bind它的Services邏輯有點像,都是透過connect回撥進行操作。但安卓的bind機制只是為了完成跨程序通訊,而鴻蒙的分散式機制是為了完成跨裝置通訊。這一點是鴻蒙勝於安卓之處,鴻蒙這樣設計,會讓所有的裝置都能虛擬為一個大終端,每個裝置都可以成為其他裝置的一個元件,從而實現軟體定義硬體。鴻蒙的核心優勢現在你明白了嗎?

10
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 《無限可能》馬斯克大腦教練作品幫助你提升記憶力