Android中的AIDL學習筆記(一)

這篇主要記錄的是AIDL的基本使用。
主要參考:Android:學習AIDL,這一篇文章就夠了(上)

Android中獨有的進程間通信方式是Binder,前面學習Service的時候就知道,Service服務端返回給客戶端的就是一個Binder,通過這個Binder完成服務端與客戶端之間的通信。
這個服務端和客戶端可以在同一個進程中,也可以在不同的進程中,對于相同的進程中的情況前面已經(jīng)說了就是繼承BInder類并將服務端的Service返回即可,但是對于不同的進程之間通信,這個就不行了,前面已經(jīng)說了使用Messenger,不過只能傳遞消息,使用AIDL能夠?qū)崿F(xiàn)的就多了,可以進行方法調(diào)用。
首先,AIDL,Android Interface Definition Language,Android接口定義語言,簡單的講,就是用來定義接口的。
然后,只需要定義接口就可以了進行進程間通信了么?不能這么說,但是這個語言是Android定義好的,語法也比較簡單,跟java很類似,我們只需要在其中簡單的定義好我們需要的接口,并寫好相應的序列化的類,然后通過IED就會幫我們生成好相應的文件,我們就可以使用這個來進行進程間通信。
使用AIDL進行進程間通信的主要流程:
如果只需要傳遞基本的數(shù)據(jù)類型,那么就沒什么問題,直接寫AIDL接口文件即可,但是如果想傳遞自定義的類對象,那么就需要考慮到序列化的問題,因為基本的數(shù)據(jù)類型默認都是可序列化的,但是我們自己寫的類是不可以的,因此就需要實現(xiàn)Android中的Parcelable接口,至于這個接口的使用,這個在前面學習Intent傳遞對象的時候就已經(jīng)說過了。
首先,需要創(chuàng)建一個實現(xiàn)了Parcelable接口的bean
然后寫這個bean對應的AIDL文件:

// Book.aidl
package com.example.gsq.servicetest.bean;
parcelable Book;

然后寫我們需要的接口AIDL文件:

// BookManager.aidl
package com.example.gsq.servicetest.bean;
import com.example.gsq.servicetest.bean.Book;
interface BookManager {
    List<Book> getBookList();
    void addBook(in Book book);
}

一定要注意包名的問題!
Book.aidl的包名需要與bean的包名一致
且BookManager.aidl中一定要導入Book.aidl的包(雖然它們已經(jīng)在一個包下)
還有就是服務端與客戶端的AIDL文件的包名也需要一致(不同的應用,所以建議放在單獨的包中)
尤其是使用AS的,一定要注意。

在AS中寫好了AIDL文件以及java bean之后,只需要點Rebuild Project,AS就會自動生成接口的java類:


Paste_Image.png

至于具體的文件內(nèi)容該怎么寫,需要注意的點,開頭的那篇文章里面介紹的很詳細,建議去學習學習。

到這里就可以開始創(chuàng)建Service服務端了
首先創(chuàng)建一個BookManager.Stub的實例,在其中實現(xiàn)我們前面定義的接口,然后在onBind中將這個實例返回給客戶端。

public class MyService3 extends Service {

    //CopyOnWriteArrayList支持冰法讀寫,確保線程同步,其中的方法都是synchronized的
    private CopyOnWriteArrayList<Book> bookList = new CopyOnWriteArrayList<>();

    private final BookManager.Stub bookManager = new BookManager.Stub() {
        @Override
        public List<Book> getBookList() throws RemoteException {
            if(bookList == null){
                bookList = new CopyOnWriteArrayList<>();
            }
            return bookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            if(bookList == null){
                bookList = new CopyOnWriteArrayList<>();
            }
            if(book != null && !bookList.contains(book)){
                bookList.add(book);
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("test_out","----->onBind");
        bookList.add(new Book("serverbook", "ser"));
        return bookManager;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("test_out","----->onUnbind");
        return true;
    }
}

我們還可以在service創(chuàng)建的時候進行一些數(shù)據(jù)的初始化等。

然后是客戶端,通過ServiceConnection獲取到服務端傳來的Binder,轉(zhuǎn)換為BookManager,然后就可以進行服務端的方法調(diào)用了。

public void addBook(){
    try {
        bookManager.addBook(new Book("book1", "tom"));
        bookManager.addBook(new Book("book2", "jack"));
        for(Book b : bookManager.getBookList()){
            Log.i("test_out","----->" + b.toString());
        }
    } catch (RemoteException e) {
        e.printStackTrace();
    }

}

ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        bookManager = BookManager.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i("test_out","----->onServiceDisconnected");
    }
};

程序運行的記過如下:
服務端:


Paste_Image.png

客戶端點擊對了addBook的按鈕之后:


Paste_Image.png

只是寫了一下AIDL的基本使用,由于剛開始學,理解不夠深入,有不正確的地方請批評指正。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容