日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

三步掌握 Android 中的 AIDL

 codingSmart 2021-10-22

第一步 創(chuàng)建 aidl 接口文件

AndroidStudio 中直接右鍵創(chuàng)建,或者自己一步步建目錄嘍。

創(chuàng)建完成后會(huì)生成一個(gè) XXX.aidl接口文件,我們需要根據(jù)需求在這個(gè)接口類(lèi)中添加接口。

在看接口怎么寫(xiě)前,先記住以下三點(diǎn):

支持的參數(shù)類(lèi)型

  1. 八種基本數(shù)據(jù)類(lèi)型;

  2. String、CharSequence;

  3. List、Map,它們中的數(shù)據(jù)類(lèi)型也應(yīng)該是AIDL支持的;

  4. 實(shí)現(xiàn)Parcelabel的引用類(lèi)型。


自定義引用類(lèi)型使用

如果要使用自定義的數(shù)據(jù)類(lèi)型,需要先為它也生成一個(gè)aidl文件,里面內(nèi)容只需兩行:

AIDL的包名; parcelable 類(lèi)名;

例如:

package com.coorchice.coorchicelibone; parcelable Role;

接著就可以創(chuàng)建對(duì)應(yīng)的java數(shù)據(jù)類(lèi)了,然后實(shí)現(xiàn)Parcelable接口,注意包名需要和aidl一模一樣!如果你對(duì)自定義類(lèi)型使用了in或者inout標(biāo)識(shí)符的話(huà),你必須再給自定義類(lèi)實(shí)現(xiàn) readFromParcel()方法。比如:

public void readFromParcel(Parcel in) {  name = in.readString();  skill = in.readString(); }

然后在定義 aidl 接口時(shí),一定要記得手動(dòng)寫(xiě)一下自定義引用類(lèi)的import!

參數(shù)修飾符

  • in: 表示參數(shù)數(shù)據(jù)只能由客戶(hù)端傳遞到服務(wù)端,基本類(lèi)型就默認(rèn)只支持in修飾符。

  • out:表示參數(shù)數(shù)據(jù)只能由服務(wù)端傳遞到客戶(hù)端。即服務(wù)端如果修改了參數(shù)對(duì)象的值,那么客戶(hù)端的值也會(huì)變化,但是服務(wù)端無(wú)法讀取到客戶(hù)端對(duì)象的值。

  • inout:表示參數(shù)數(shù)據(jù)能夠雙向傳遞。


定義服務(wù)接口

現(xiàn)在,我們可以開(kāi)始定義服務(wù)接口了!這里定義的服務(wù)接口就是后面我們需要在客戶(hù)端調(diào)用的。

CoorChice 定義了3個(gè)接口,接著編譯一下。然后編譯器會(huì)自動(dòng)根據(jù)我們定義的接口生成對(duì)應(yīng)的類(lèi)。

注意:自定義的類(lèi)必須加in、out、inout等標(biāo)識(shí)符,否則會(huì)報(bào)錯(cuò)!


編譯后生成的類(lèi)解析

編譯之后編譯器自動(dòng)幫我們生成了一個(gè)服務(wù)接口類(lèi)名.Stub的抽象類(lèi),它繼承自 Binder,然后實(shí)現(xiàn)了我們定義的服務(wù)接口(注意我們的服務(wù)接口實(shí)現(xiàn)了IInterface接口)。嗯,重點(diǎn)是它是一個(gè)Binder!它就是我們用來(lái)進(jìn)行 Binder 通訊的!

其實(shí),Android 的 AIDL 就是讓編譯器幫助我們生成一個(gè)實(shí)現(xiàn)了我們接口的 Binder,以幫助我們簡(jiǎn)化開(kāi)發(fā)。當(dāng)然,如果你了解原理的話(huà),也可以自己寫(xiě)。

下面我們一步一步來(lái)看看這編譯器生成的類(lèi)都有些什么?

1. 服務(wù)接口實(shí)現(xiàn)IInterface

public interface AIDLDemo extends android.os.IInterface {    ... }

編譯器根據(jù)我們寫(xiě)的服務(wù)接口,重新生成了一個(gè)接口,唯一的區(qū)別就是新的接口繼承了IInterface接口。這個(gè)接口是干什么的呢?

public interface IInterface {    public IBinder asBinder(); }

可以看到,它只有一個(gè)接口方法。這個(gè)方法用來(lái)定義將實(shí)現(xiàn)接口的類(lèi)應(yīng)該具備返回一個(gè)與之相關(guān)聯(lián)的Binder的功能,以提供通訊能力。一般實(shí)現(xiàn)這個(gè)方法的類(lèi)自己本身就會(huì)去繼承Binder。

這樣的設(shè)計(jì)使得Binder機(jī)制不用關(guān)心具體的接口是什么,只要是IInterface就行。事實(shí)上相當(dāng)于是我們?cè)?code>IInterface接口的基礎(chǔ)上擴(kuò)展了接口功能,本質(zhì)上還是一個(gè)IInterface,所以Binder能夠認(rèn)出它。

2. 繼承Binder,實(shí)現(xiàn)服務(wù)接口

要進(jìn)行 Binder 通訊,我們自然需要一個(gè) Binder;要實(shí)現(xiàn)我們定義的服務(wù)接口功能,自然就需要實(shí)現(xiàn)服務(wù)接口。那么需要滿(mǎn)足這兩個(gè)條件怎么辦?很簡(jiǎn)單,繼承 Binder,然后實(shí)現(xiàn)服務(wù)接口就行。

編譯器為我們生成的類(lèi)中有一個(gè)內(nèi)部類(lèi)Stub就是這么干的。事實(shí)上,這樣的設(shè)計(jì)隨處可見(jiàn)。你可以看看 CoorChice 這篇文章《3分鐘看懂Activity啟動(dòng)流程》http://www.jianshu.com/p/9ecea420eb52 中出現(xiàn)的ActivityManagerNative 就是這么干的,雖然它是代理系統(tǒng)的ActivityManagerService,但是模式都是一樣的。

public static abstract class Stub extends android.os.Binder implements com.coorchice.coorchicelibone.AIDLDemo


3. Binder需要綁定服務(wù)接口,定義DESCRIPTOR描述

為了一個(gè)Binder和一個(gè)特定服務(wù)接口綁定,以對(duì)外提供功能,需要給Binder定義一個(gè)DESCRIPTOR描述,表示我這個(gè)Binder是提供特定功能鏈接的,不是隨便可以用的。

通常,DESCRIPTOR描述會(huì)直接使用包名 + 服務(wù)接口。

4. 實(shí)現(xiàn)asInterface()供客戶(hù)端調(diào)用

作為一個(gè)服務(wù)提供者,為了能夠給調(diào)用者提供遠(yuǎn)程功能,自然需要能夠提供和遠(yuǎn)程服務(wù)關(guān)聯(lián)的 Binder 來(lái)通訊,請(qǐng)求服務(wù)。獲取 Binder 的接口就是 IInterface 中定義的。

先查詢(xún)一下獲取到的和遠(yuǎn)程 Service 通訊的 Binde 中是否已經(jīng)添加了功能接口的實(shí)現(xiàn),如果沒(méi)有則創(chuàng)建代理,通過(guò)代理間接的操作 Binder 和遠(yuǎn)程 Service 通訊,實(shí)現(xiàn)功能。

思考:既然我們已經(jīng)獲取到了能夠直接和遠(yuǎn)程 Service 通訊的Binder,為什么不直接操作它去向遠(yuǎn)程 Service 請(qǐng)求服務(wù)呢?

確實(shí),我們可以直接操作 Binder 向遠(yuǎn)程 Service 請(qǐng)求服務(wù),但這過(guò)程中有很多繁瑣的操作,還有一些 code碼的區(qū)別,如果不封裝隔離的話(huà),隨著功能的擴(kuò)展,我們將很難再去維護(hù)這段通訊邏輯。還有就是通過(guò)這種方式統(tǒng)一的管理通訊邏輯使得它可以隨處使用,而不用沒(méi)一個(gè)要用的地方都去寫(xiě)一遍。

既然是要代理和遠(yuǎn)程服務(wù)通訊,而且通訊的目的是為了請(qǐng)求服務(wù)接口定義的功能,那么很自然就能想到去實(shí)現(xiàn)服務(wù)接口,然后再對(duì)應(yīng)的接口方法中實(shí)現(xiàn)邏輯即可。這樣就可以分開(kāi)來(lái)維護(hù)客戶(hù)端和服務(wù)端的對(duì)應(yīng)的每個(gè)功能了。

所以,我們的代理也需要實(shí)現(xiàn)服務(wù)接口,然后在代理中操作遠(yuǎn)程通訊的Binder進(jìn)行通訊。

5. 重寫(xiě)onTransact()

在Binder通訊中,一個(gè)和遠(yuǎn)程端通訊的Binder::transact()方法,會(huì)觸發(fā)通訊目標(biāo)端執(zhí)行Binder::onTransact(),就是說(shuō)這個(gè)時(shí)候已經(jīng)收到了通訊發(fā)起端的請(qǐng)求了??纯催@個(gè)方法的參數(shù):

public boolean transact(int code, Parcel data, Parcel reply, int flags){}
參數(shù)解釋
code用來(lái)標(biāo)識(shí)指令,即這次通訊是使用什么功能。需要客戶(hù)端和服務(wù)端約定好code碼。
data來(lái)自發(fā)送端的數(shù)據(jù)包。
reply來(lái)自發(fā)送端的接收包,往這個(gè)包中寫(xiě)數(shù)據(jù),就相當(dāng)于給發(fā)送端返回?cái)?shù)據(jù)。
flags特殊操作標(biāo)識(shí)。

對(duì)應(yīng)的我們?cè)诳纯?code>Binder::transact()方法:

public boolean transact(int code, Parcel data, Parcel reply, int flags){}
參數(shù)解釋
code用來(lái)標(biāo)識(shí)指令,即這次通訊是使用什么功能。需要客戶(hù)端和服務(wù)端約定好code碼。
data發(fā)送給遠(yuǎn)程端的數(shù)據(jù)包。
reply用于讓遠(yuǎn)程端寫(xiě)回復(fù)數(shù)據(jù)的數(shù)據(jù)包
flags特殊操作標(biāo)識(shí)。

可以看出來(lái),兩個(gè)是成對(duì)的操作。Binder::transact()操作是一個(gè)阻塞式的操作,就是說(shuō)在這個(gè)方法執(zhí)行返回成功后,直接從reply中讀取的數(shù)據(jù)就是遠(yuǎn)程端在Binder::onTransact()中填充的數(shù)據(jù)。

這個(gè)過(guò)程可以大概抽象成這個(gè)樣子:

在編譯器自動(dòng)幫我們生成的onTransact()中,會(huì)讀取data中數(shù)據(jù),然后調(diào)用對(duì)應(yīng)的方法(這個(gè)方法還沒(méi)實(shí)現(xiàn),所以我們可以繼承Stub然后重寫(xiě),以實(shí)現(xiàn)在服務(wù)端處理的效果)。比如這個(gè)樣子:

第二步. 創(chuàng)建一個(gè)遠(yuǎn)程 Service

我們正常創(chuàng)建一個(gè)支持其它應(yīng)用調(diào)用的 Service,Service  怎么創(chuàng)建就不說(shuō)。主要看看在 Service 最重要的一步,就是繼承上面生成的Stub,然后自定義一個(gè) Binder。

接著,在onBinder()中返回一個(gè)上面這個(gè)Binder的實(shí)例給客戶(hù)端。

第三步. 客戶(hù)端鏈接Binder

首先重要的一步是,我們必須把這個(gè)aidl文件夾拷貝到客戶(hù)端工程的對(duì)應(yīng)目錄下。

包名不能變!

包名不能變!

包名不能變!

然后通過(guò)綁定的方式啟動(dòng)這個(gè)Service。

總結(jié)

恭喜你!現(xiàn)在你已經(jīng)掌握AIDL了!

實(shí)際上,從上面的分析可以看出,AIDL其實(shí)就是對(duì)Binder機(jī)制的簡(jiǎn)化封裝。Android這一套封裝使得我們?cè)谧约憾xService時(shí)方便了許多!你可以不用去編寫(xiě)繁雜的交互,看看編譯器自動(dòng)生成的文件有多不堪入目吧。

但是不管怎么封裝,Binder通訊機(jī)制的靈魂是不變的,所以要更好的理解這個(gè)過(guò)程,你可以看看CoorChice的這幾篇文章:

《從getSystemService()開(kāi)始,開(kāi)擼Binder通訊機(jī)制》http://www.jianshu.com/p/1050ce12bc1e;

《能用【白話(huà)文】來(lái)分析Binder通訊機(jī)制?》http://www.jianshu.com/p/fe816777f2cf;

《Binder機(jī)制之一次響應(yīng)的故事》

http://www.jianshu.com/p/4fba927dce05

這幾篇文章從我們接觸最多的上層入手,一步步分析到了 Binder 內(nèi)核層,描述了內(nèi)核的 Bidner 驅(qū)動(dòng)是如何實(shí)現(xiàn)一次完整的 c/s 通訊的。

與之相關(guān)

從未如此驚艷!你好,SuperTextView

Android-Material Design風(fēng)格MVP模式的新聞App(視頻圖片音樂(lè))

微信號(hào):code-xiaosheng

公眾號(hào)

「code小生」

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多