在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文解析鴻蒙系統(tǒng)中的HDF架構(gòu)

鴻蒙系統(tǒng)HarmonyOS ? 來源:CSDN博主 ? 作者:悠然紅茶 ? 2021-03-25 16:06 ? 次閱讀

1 鋪墊一下

鴻蒙系統(tǒng)終于公開源代碼了,正可謂“千呼萬喚始出來”。筆者也手癢下載了一套代碼,并研讀了一二。這里就先編寫一篇關(guān)于HDF的文檔。

其實,不同讀碼人都會有各自讀代碼的習(xí)慣和切入點,我之所以從HDF入手,完全是出于偶然。因為在一開始讀官方文檔時,看到說一部機器可以操作另一部機器的設(shè)備,為此,設(shè)備需要有一個重要的PublishService()函數(shù)。這種跨設(shè)備操作的能力也是鴻蒙的一大特色,應(yīng)該比較有趣,于是就以這個PublishService()為切入點,開始研讀代碼,慢慢就涉及了HDF的更多知識,現(xiàn)在是時候整理出來了。

所謂HDF,應(yīng)該是Harmony Driver Fundation的縮寫,說到底是鴻蒙形成的一套管理設(shè)備驅(qū)動的框架模型,也被稱為“驅(qū)動子系統(tǒng)”。在官網(wǎng)的文檔里介紹說這個驅(qū)動子系統(tǒng)具有以下重要能力:

彈性化的框架能力

規(guī)范化的驅(qū)動接口

組件化的驅(qū)動模型

歸一化的配置界面

讀完這四句話,不免讓人覺得好像明白了什么,又好像什么都沒明白。好吧,我還是按自己的習(xí)慣直接讀代碼吧。

為了便于理解代碼,我習(xí)慣于把軟件圖形化。為此,我介紹一點我的圖形表達方法。在我讀Java代碼時,如果要表達A類對象的某個成員引用了另一個B類對象,我常常會這樣繪制:

但是HDF的代碼是用C寫的,所以對應(yīng)的圖形表達法也要有所變化。我們要區(qū)分一下:

1)A結(jié)構(gòu)以某成員組合了另一個B結(jié)構(gòu);

2)A結(jié)構(gòu)某成員是個指向B的指針;

這兩種情況可以分別表示為:

另外,有時候HDF會使用C語言的一些技巧進行鏈表表達或基類轉(zhuǎn)換,那么上面的圖形畫出來就會很累贅,針對這種情況,我有時候會這樣表達(以DevmgrService結(jié)構(gòu)為例):

可以看出,DevmgrService繼承于IDevmgrService,而IDevmgrService又在起始處組合了一個HdfDeviceObject(有時候也可以說是繼承于HdfDeviceObject)。也就是說:

1)DevmgrService的起始地址;

2)DevmgrService內(nèi)部IDevmgrService部分的起始地址;

3)IDevmgrService內(nèi)部HdfDeviceObject部分的起始地址;

這3個起始地址其實是同一處。用這種表達法,我們就不必畫出3個分離的框圖了。

好了,鋪墊部分就先寫這么多,下面我們來看HDF的實際內(nèi)容。

2 DevmgrService和Dev Host

我們以hi3516 dv300為例,其系統(tǒng)一啟動,會運行到SystemInit(),其中會調(diào)用DeviceManagerStart()啟動與HDF相關(guān)的部分:

【vendor/hisi/hi35xx/hi3516dv300/module_init/src/System_init.c】

void SystemInit(void)

{

. . . . . .

#ifdef LOSCFG_DRIVERS_HDF

if (DeviceManagerStart()) {

PRINT_WARN("No drivers need load by hdf manager!");

}

#endif

. . . . . .

}

2.1 啟動DeviceManager

【drivers/hdf/lite/manager/src/Devmgr_service_start.c】

int DeviceManagerStart()

{

struct IDevmgrService *instance = DevmgrServiceGetInstance();

if (instance == NULL || instance->StartService == NULL) {

HDF_LOGE("Device manager start failed, service instance is null!");

return HDF_FAILURE;

}

struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE, DEV_MGR_NODE_PERM);

if (ioService != NULL) {

static struct HdfIoDispatcher dispatcher = {

.Dispatch = DeviceManagerDispatch,

};

ioService->dispatcher = &dispatcher;

ioService->target = (struct HdfObject *)&instance->object;

}

return instance->StartService(instance);

}

簡單地說,要啟動DeviceManager服務(wù),就得先獲取一個DevmgrService實例,然后調(diào)用它的StartService(),又因為DevmgrService繼承于IDevmgrService,所以可以強制轉(zhuǎn)換成IDevmgrService*。

2.1.1 獲取DevmgrService單例

獲取實例時,其實用到了HDF機制提供的一個對象管理器,相關(guān)代碼如下:

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

struct IDevmgrService *DevmgrServiceGetInstance()

{

static struct IDevmgrService *instance = NULL; // 注意是static的,表示是個靜態(tài)單例

if (instance == NULL) {

instance = (struct IDevmgrService *)

HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);

}

return instance;

}

以后我們會看到,這個HdfObjectManagerGetObject()會在多個地方調(diào)用,以便獲取不同的HDF對象。說起來也簡單,HDF機制里有一張表,記錄著該如何創(chuàng)建、釋放一些重要的HDF對象,該表格為g_liteObjectCreators:

【drivers/hdf/lite/manager/src/Devlite_object_config.c】

static const struct HdfObjectCreator g_liteObjectCreators[]

基于讀到的代碼,我們可以畫出這個表格:

概念還是比較簡單的,如果系統(tǒng)中的DevmgrService單例對象已經(jīng)存在,就使用之。否則就利用HDF對象管理器創(chuàng)建一個DevmgrService對象。對于HDF對象管理器而言,不同類型的HDF對象,需要用到不同的創(chuàng)建函數(shù),所以要查一下上表。比如DevmgrService對應(yīng)的創(chuàng)建函數(shù)就是DevmgrServiceCreate(),該函數(shù)代碼如下:

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

struct HdfObject *DevmgrServiceCreate()

{

static bool isDevMgrServiceInit = false;

static struct DevmgrService devmgrServiceInstance;

if (!isDevMgrServiceInit) {

if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {

return NULL;

}

isDevMgrServiceInit = true;

}

return (struct HdfObject *)&devmgrServiceInstance; // ???HdfObject,有小問題!

}

在“創(chuàng)建”時,如果發(fā)現(xiàn)是首次創(chuàng)建,則調(diào)用一個類似構(gòu)造函數(shù)的DevmgrServiceConstruct()函數(shù),來初始化對象里的函數(shù)表。這種做法是用C語言實現(xiàn)面向?qū)ο蟾拍畹某S米龇ā2贿^,此處的代碼有一個小bug,即最后那個強制轉(zhuǎn)換,從目前看到的代碼來說,DevmgrService間接繼承于HdfDeviceObject,而HdfDeviceObject并不繼承于HdfObject,所以是不應(yīng)該這樣強制轉(zhuǎn)換的,除非HdfDeviceObject的第一個成員從“IDeviceIoService*”改為“IDeviceIoService”,我估計最早的代碼就是IDeviceIoService,后來因為某些原因,變成了指針形式,至于以后具體該怎么修正,這個就讓鴻蒙的工程師去費腦筋吧。DevmgrService的構(gòu)造函數(shù)如下:

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

static bool DevmgrServiceConstruct(struct DevmgrService *inst)

{

if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {

HDF_LOGE("%s mutex init failed", __func__);

return false;

}

struct IDevmgrService *devMgrSvcIf = (struct IDevmgrService *)inst;

if (devMgrSvcIf != NULL) {

devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;

devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;

devMgrSvcIf->StartService = DevmgrServiceStartService;

devMgrSvcIf->AcquireWakeLock = DevmgrServiceAcquireWakeLock;

devMgrSvcIf->ReleaseWakeLock = DevmgrServiceReleaseWakeLock;

HdfSListInit(&inst->hosts);

}

return true;

}

2.1.2 HdfIoServiceBind()

啟動DeviceManager時,第二個重要的動作是調(diào)用HdfIoServiceBind():

struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE, DEV_MGR_NODE_PERM);

這一步在做什么呢?我們可以這樣理解,DevmgrService作為一個核心的系統(tǒng)服務(wù),我們希望能像訪問虛文件系統(tǒng)的文件那樣打開它,并進一步向它傳遞諸如AttachDevice、StartServie......這樣的語義。這些語義最終會執(zhí)行到上面列舉的DevmgrServiceAttachDevice、DevmgrServiceStartService等函數(shù)。

我們不必列舉太多代碼,下面是我繪制的一張關(guān)于DeviceManagerStart()的調(diào)用關(guān)系示意圖,可供參考:

圖中已經(jīng)明確注明,DevmgrService在虛文件系統(tǒng)里對應(yīng)的路徑應(yīng)該是“/dev/dev_mgr”,而上面調(diào)用HdfIoServiceBind()后,實際上建立了一個文件系統(tǒng)的inode節(jié)點,示意圖如下:

HdfVNodeAdapter的target在最后賦值為(struct HdfObject*)&instance->object,說到底其實就是指向了DevmgrService。

2.1.3 執(zhí)行DevmgrService的StartService

接下來是啟動DeviceManager的第三步,調(diào)用instance->StartService(),這一步其實是在調(diào)用DevmgreviceStartService()函數(shù)。

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

int DevmgrServiceStartService(struct IDevmgrService *inst)

{

struct DevmgrService *dmService = (struct DevmgrService *)inst;

if (dmService == NULL) {

HDF_LOGE("Start device manager service failed, dmService is null");

return HDF_FAILURE;

}

return DevmgrServiceStartDeviceHosts(dmService);

}

主要就是在調(diào)用一個DevmgrServiceStartDeviceHosts()函數(shù)。這個函數(shù)應(yīng)該算是個重量級函數(shù),它會負責(zé)建立起DevmgrService內(nèi)部主要的數(shù)據(jù)結(jié)構(gòu)。我們先繪制一下該函數(shù)第一層次的調(diào)用關(guān)系,如下圖:

在進一步深入代碼細節(jié)之前,我們最好先大概說明一下。在鴻蒙HDF架構(gòu)里,有一個“設(shè)備Host”的概念,根據(jù)官方的文檔,我們大概可以知道,一個Host用于整合若干業(yè)務(wù)相近的設(shè)備,這個原則被稱為相似相容原則。為了實現(xiàn)這個原則,HDF構(gòu)造了一系列數(shù)據(jù)結(jié)構(gòu),我們列舉一下:

1)HdfHostInfo

2)DevHostServiceClnt

3)DevHostService

4)HdfDevice

5)HdfDeviceNode

. . . . . .

我們當(dāng)然沒必要在一篇文檔里列出所有的數(shù)據(jù)結(jié)構(gòu),只需先明白:

1)設(shè)備管理服務(wù)(DevmgrService)內(nèi)部可以管理若干Host;

2)每個Host內(nèi)部可以整合若干業(yè)務(wù)相近的設(shè)備;

3)每個Host可以拆分成兩個部分:DevHostServiceClnt 和 DevHostService;

4)每個DevHostService可以添加多個設(shè)備;

從上面的調(diào)用關(guān)系圖中,我們可以看到DevmgrServiceStartDeviceHosts()函數(shù)的主要行為是:

1)先獲取一個驅(qū)動安裝器(單例)對象;

2)解析系統(tǒng)配置信息,將其轉(zhuǎn)換成一個以HdfHostInfo為表項的列表,這個就對應(yīng)著系統(tǒng)里所有的host;

3)遍歷這張HdfHostInfo列表,為每個HdfHostInfo節(jié)點創(chuàng)建一個對應(yīng)的DevHostServiceClnt對象;

4)新創(chuàng)建的DevHostServiceClnt節(jié)點會被插入DevmgrService的hosts列表中;

5)針對每個HdfHostInfo節(jié)點,利用剛剛獲取的驅(qū)動安裝器具體啟動該host。

2.1.3.1獲取驅(qū)動安裝器

現(xiàn)在我們詳細看上圖中調(diào)用的關(guān)鍵函數(shù)。

installer = DriverInstallerGetInstance();

先拿到一個驅(qū)動安裝器。

struct IDriverInstaller *DriverInstallerGetInstance()

{

static struct IDriverInstaller *installer = NULL;

if (installer == NULL) {

installer = (struct IDriverInstaller *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DRIVER_INSTALLER);

}

return installer;

}

又看到HdfObjectManagerGetObject(),于是我們查前文那張表,可以找到驅(qū)動安裝器對應(yīng)的創(chuàng)建函數(shù)是DriverInstallerCreate():

【drivers/hdf/frameworks/core/manager/src/Hdf_driver_installer.c】

struct HdfObject *DriverInstallerCreate(void)

{

static bool isDriverInstInit = false;

static struct DriverInstaller driverInstaller;

if (!isDriverInstInit) {

DriverInstallerConstruct(&driverInstaller);

isDriverInstInit = true;

}

return (struct HdfObject *)&driverInstaller;

}

用的是一個單例的DriverInstaller對象。

2.1.3.2 獲取HdfHostInfo列表

啟動所有hosts的第二步,是獲取一個HdfHostInfo列表:

HdfAttributeManagerGetHostList(&hostList)

我們摘選該函數(shù)的主要句子,如下:

【drivers/hdf/lite/manager/src/Hdf_attribute_manager.c】

bool HdfAttributeManagerGetHostList(struct HdfSList *hostList)

{

. . . . . .

hdfManagerNode = GetHdfManagerNode(HcsGetRootNode());

. . . . . .

hostNode = hdfManagerNode->child;

while (hostNode != NULL) {

struct HdfHostInfo *hostInfo = HdfHostInfoNewInstance();

. . . . . .

if (!GetHostInfo(hostNode, hostInfo)) {

HdfHostInfoFreeInstance(hostInfo);

hostInfo = NULL;

hostNode = hostNode->sibling;

continue;

}

hostInfo->hostId = hostId;

if (!HdfSListAddOrder(hostList, &hostInfo->node, HdfHostListCompare)) {

HdfHostInfoFreeInstance(hostInfo);

hostInfo = NULL;

hostNode = hostNode->sibling;

continue;

}

hostId++;

hostNode = hostNode->sibling;

}

return true;

}

我們稍微擴展一點知識來說明一下。在鴻蒙系統(tǒng)中,有一些系統(tǒng)級的配置文件,叫做HCS文件。系統(tǒng)可以利用類似hc-gen這樣的工具,根據(jù)配置文件生成二進制碼。當(dāng)HDF啟動時,它會將二進制信息傳給DriverConfig模塊。該模塊會將二進制碼轉(zhuǎn)換成配置樹,并向開發(fā)者提供API去查詢這棵樹。

配置樹的根節(jié)點是g_hcsTreeRoot,節(jié)點類型為DeviceResourceNode。這棵配置樹里有一個特殊的節(jié)點,具有“hdf_manager”屬性,上面代碼中調(diào)用GetHdfManagerNode()一句,就是在獲取這個特殊節(jié)點。接著,上面的代碼里會嘗試遍歷該節(jié)點的所有child,并將每個child的信息整理進一個HdfHostInfo對象里。注意此時就會給HdfHostInfo分派一個hostId了,這個hostId后續(xù)還會用到。所有讀出的HdfHostInfo節(jié)點會按照其內(nèi)記錄的優(yōu)先級進行排序,并連成一個列表,優(yōu)先級越高越靠近表頭。

2.1.3.3 遍歷HdfHostInfo列表

得到HdfHostInfo列表后,緊接著就會嘗試遍歷這張表。因為每個HdfHostInfo節(jié)點代表的就是一個host,所以每讀取一個HdfHostInfo,就會對應(yīng)地生成一個DevHostServiceClnt對象。這些生成的DevHostServiceClnt都會插入到DevmgrService的hosts列表中。

每讀取一個HdfHostInfo信息后,就會利用驅(qū)動安裝器,啟動對應(yīng)的host。

2.1.3.4啟動host

啟動host的動作是installer->StartDeviceHost()一步,它的調(diào)用關(guān)系如下:

大家還記得前文我說過,每個Host可以拆分成兩個部分:DevHostServiceClnt 和 DevHostService。這個就體現(xiàn)在上面的調(diào)用關(guān)系里。

StartDeviceHost一開始就會創(chuàng)建一個DevHostService對象,

【drivers/hdf/frameworks/core/manager/src/Hdf_driver_installer.c】

static int DriverInstallerStartDeviceHost(uint32_t devHostId, const char *devHostName)

{

struct IDevHostService *hostServiceIf = DevHostServiceNewInstance(devHostId, devHostName);

if ((hostServiceIf == NULL) || (hostServiceIf->StartService == NULL)) {

HDF_LOGE("hostServiceIf or hostServiceIf->StartService is null");

return HDF_FAILURE;

}

int ret = hostServiceIf->StartService(hostServiceIf);

if (ret != HDF_SUCCESS) {

HDF_LOGE("Start host service failed, ret is: %d", ret);

DevHostServiceFreeInstance(hostServiceIf);

}

return ret;

}

隨后調(diào)用的StartService,實際上對應(yīng)DevHostServiceStartService()函數(shù):

【drivers/hdf/frameworks/core/host/src/Devhost_service.c】

static int DevHostServiceStartService(struct IDevHostService *service)

{

struct DevHostService *hostService = (struct DevHostService*)service;

if (hostService == NULL) {

HDF_LOGE("Start device service failed, hostService is null");

return HDF_FAILURE;

}

return DevmgrServiceClntAttachDeviceHost(hostService->hostId, service);

}

此處調(diào)用的DevmgrServiceClntAttachDeviceHost()函數(shù),內(nèi)部涉及的內(nèi)容挺多,我打算在下一篇文檔里再細說。現(xiàn)在我們已經(jīng)對“啟動DeviceManager”的流程有了一點初步的認識,為了便于理解里面host的部分,我們畫一張示意圖總結(jié)一下,繪圖如下:

編輯:hfy

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2634

    瀏覽量

    66348
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1975

    瀏覽量

    30202
  • HDF框架
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    2768
收藏 人收藏

    評論

    相關(guān)推薦

    【書籍評測活動NO.53】鴻蒙操作系統(tǒng)設(shè)計原理與架構(gòu)

    知識的“指導(dǎo)老師”。 以華為官方為主導(dǎo),選擇最權(quán)威的參考資料,由鴻蒙開發(fā)團隊的專家親自執(zhí)筆的新書《鴻蒙操作系統(tǒng)設(shè)計原理與架構(gòu)》即將上市啦 ! 對與
    發(fā)表于 12-16 15:10

    軟通動力出席鴻蒙生態(tài)旅行業(yè)千帆啟航儀式

    風(fēng)景區(qū)出席峰會,共同出席鴻蒙生態(tài)旅行業(yè)千帆啟航儀式。作為受邀分享的服務(wù)商伙伴,軟通動力還展示了自身在鴻蒙生態(tài)旅行業(yè)的探索與實踐。 ? 鴻蒙
    的頭像 發(fā)表于 12-10 09:08 ?220次閱讀

    加速行業(yè)深度融合,軟通動力出席鴻蒙生態(tài)旅行業(yè)千帆啟航儀式

    北京2024年12月9日?/美通社/ -- 12月6日,鴻蒙生態(tài)旅行業(yè)峰會在北京成功召開。峰會由華為主辦,旨在聯(lián)動業(yè)界伙伴,展示鴻蒙旅行業(yè)的深度融合和發(fā)展前景,為
    的頭像 發(fā)表于 12-09 15:10 ?109次閱讀
    加速行業(yè)深度融合,軟通動力出席<b class='flag-5'>鴻蒙</b>生態(tài)<b class='flag-5'>文</b>旅行業(yè)千帆啟航儀式

    Taro 鴻蒙技術(shù)內(nèi)幕系列(三) - 多語言場景下的通用事件系統(tǒng)設(shè)計

    作者:京東零售 朱天健 基于 Taro 打造的京東鴻蒙 APP 已跟隨鴻蒙 Next 系統(tǒng)公測,本系列文章將深入解析 Taro 如何實現(xiàn)使用 React 開發(fā)高性能
    的頭像 發(fā)表于 11-27 11:42 ?201次閱讀
    Taro <b class='flag-5'>鴻蒙</b>技術(shù)內(nèi)幕系列(三) - 多語言場景下的通用事件<b class='flag-5'>系統(tǒng)</b>設(shè)計

    Taro鴻蒙技術(shù)內(nèi)幕系列():如何將React代碼跑在ArkUI上

    基于 Taro 打造的京東鴻蒙 APP 已跟隨鴻蒙 Next 系統(tǒng)公測,本系列文章將深入解析 Taro 如何實現(xiàn)使用 React 開發(fā)高性能鴻蒙
    的頭像 發(fā)表于 10-25 17:24 ?317次閱讀
    Taro<b class='flag-5'>鴻蒙</b>技術(shù)內(nèi)幕系列(<b class='flag-5'>一</b>):如何將React代碼跑在ArkUI上

    鴻蒙跨端實踐-JS虛擬機架構(gòu)實現(xiàn)

    類似的框架,我們需要自行實現(xiàn)以確保核心基礎(chǔ)能力的完整。 鴻蒙虛擬機的開發(fā)經(jīng)歷了從最初 ArkTs2V8 到 JSVM + Roma新架構(gòu)方案 。在此過程,我們實現(xiàn)了完整的鴻蒙版的“J
    的頭像 發(fā)表于 09-30 14:42 ?2418次閱讀
    <b class='flag-5'>鴻蒙</b>跨端實踐-JS虛擬機<b class='flag-5'>架構(gòu)</b>實現(xiàn)

    鴻蒙系統(tǒng)三防平板怎么樣

    鴻蒙系統(tǒng)三防平板是款功能強大、性能卓越的平板電腦,其獨特的三防設(shè)計使其成為各種惡劣環(huán)境下的理想選擇。無論是戶外探險、工地作業(yè)還是軍事應(yīng)用,鴻蒙系統(tǒng)
    發(fā)表于 04-12 14:26

    鴻蒙開發(fā)實戰(zhàn):【Hdf Framework】

    該倉主要存放OpenHarmony驅(qū)動子系統(tǒng)核心源碼信息(包括驅(qū)動框架、配置管理、配置解析、驅(qū)動通用框架模型、硬件通用平臺能力接口等),旨在為開發(fā)者提供更精準、更高效的開發(fā)環(huán)境,力求做到次開發(fā),多
    的頭像 發(fā)表于 03-21 20:29 ?514次閱讀
    <b class='flag-5'>鴻蒙</b>開發(fā)實戰(zhàn):【<b class='flag-5'>Hdf</b> Framework】

    鴻蒙OS之UI架構(gòu)解析

    填充數(shù)據(jù),就能正常顯示個列表了。 數(shù)據(jù)從哪來 可以看到上面的代碼里是沒有數(shù)據(jù)的,只有個空數(shù)組。我們想要從網(wǎng)絡(luò)獲取數(shù)據(jù)。那么,數(shù)據(jù)怎么來呢?最簡單粗暴的寫法就是在aboutToAppear()異步
    發(fā)表于 02-20 15:36

    【JAVA UI】【HarmonyOS】【Demo】 鴻蒙如何進行 xml 解析

    鴻蒙鴻蒙如何進行數(shù)據(jù)解析 【問題描述】有時候我們從服務(wù)器獲取是 xml 格式數(shù)據(jù),我們需要將 xml 轉(zhuǎn)化成 model 對象,該如何使用呢?下面舉個例子說明下,將分以下幾步進行
    的頭像 發(fā)表于 02-19 15:59 ?573次閱讀
    【JAVA UI】【HarmonyOS】【Demo】 <b class='flag-5'>鴻蒙</b>如何進行 xml <b class='flag-5'>解析</b>

    華為鴻蒙系統(tǒng)怎么樣 華為鴻蒙系統(tǒng)和安卓系統(tǒng)的區(qū)別

    和穩(wěn)定性。與此同時,鴻蒙系統(tǒng)與安卓系統(tǒng)架構(gòu)、功能和生態(tài)系統(tǒng)方面都存在些區(qū)別和特點,下面將詳細
    的頭像 發(fā)表于 02-02 14:54 ?1746次閱讀

    質(zhì)疑鴻蒙系統(tǒng)的是什么人群?為什么要杠

    2019 年,HarmonyOS 鴻蒙操作系統(tǒng)正式發(fā)布。但接下來很長的時間里,鴻蒙都是在自研的基礎(chǔ)上,內(nèi)置個 AOSP 架構(gòu)。目的很簡單,
    的頭像 發(fā)表于 01-22 22:20 ?319次閱讀
    質(zhì)疑<b class='flag-5'>鴻蒙</b><b class='flag-5'>系統(tǒng)</b>的是什么人群?為什么要杠

    鴻蒙系統(tǒng)和安卓的區(qū)別 鴻蒙系統(tǒng)有什么特別之處

    鴻蒙系統(tǒng)是華為公司自主研發(fā)的款全新操作系統(tǒng),旨在替代安卓系統(tǒng)鴻蒙
    的頭像 發(fā)表于 01-18 11:45 ?1.2w次閱讀

    很多人質(zhì)疑鴻蒙,那它算不算國產(chǎn)操作系統(tǒng)

    。這使得鴻蒙更加靈活、安全、高效。 安卓則采用單設(shè)備架構(gòu),這意味著它的多設(shè)備協(xié)作能力較弱,數(shù)據(jù)共享相對不便。 3、安全性 鴻蒙操作系統(tǒng)采用
    發(fā)表于 01-17 22:04

    鴻蒙系統(tǒng)和安卓的區(qū)別哪個好用

    些問題,如性能、隱私安全等。而安卓系統(tǒng)是由谷歌開發(fā)和推廣的移動設(shè)備操作系統(tǒng),目前在全球范圍內(nèi)占據(jù)主導(dǎo)地位。 鴻蒙系統(tǒng)
    的頭像 發(fā)表于 01-11 11:15 ?1952次閱讀
    主站蜘蛛池模板: 8天堂资源在线 | 亚欧成人中文字幕一区 | 久久久久免费 | 91色在线视频 | 亚洲精品91香蕉综合区 | 99久久综合狠狠综合久久男同 | 特级一级全黄毛片免费 | 亚洲国产综合人成综合网站00 | 乡村乱人伦短小说 | 亚洲一区二区免费看 | 亚洲精品乱码久久久久久蜜桃图片 | 国久久| 欧美乱淫| 秋霞一级特黄真人毛片 | 天天干天天干 | 男女视频在线看 | 激情5月婷婷 | 日本a级片免费 | 国产一级做a爰片久久毛片男 | 成人性欧美丨区二区三区 | 四虎亚洲精品 | 精品国产自在现线看久久 | 99视频网站 | 91噜噜噜| 男女免费观看视频 | 手机在线观看国产精选免费 | 色佬网 | 免费看国产黄色片 | 男人j进入女人j视频大全 | 亚洲免费视频观看 | 日本黄网站高清色大全 | xx视频在线| 午夜精品久久久久久久第一页 | 国产色av | 亚洲欧美日韩特级毛片 | 天堂资源在线bt种子 | 久久永久免费视频 | 在线理论视频 | 日本黄色大片在线播放视频免费观看 | 性xxx无遮挡 | 色玖玖 |