Android IPC之AIDL

在前面的文章中介紹了Messenger,Messenger的缺點就是一次只能處理一條消息,不支持多并發(fā),而且只支持?jǐn)?shù)據(jù)的傳輸,不支持方法的調(diào)用。那么在這一篇文章中 將為大家介紹更強大的IPC工具,AIDL。

AIDL 全稱為Android Interface Definition Language,安卓接口定義語言,也是Android實現(xiàn)IPC的方式之一。接下來將為大家介紹AIDL的使用。

服務(wù)端:
服務(wù)端需要創(chuàng)建一個Service監(jiān)聽客戶端的連接,并創(chuàng)建AIDL文件,將暴漏給客戶端的方法在這個文件中聲明。最后在Service中實現(xiàn)AIDL中的方法。

客戶端:
綁定服務(wù)端的Service,并將Binder對象轉(zhuǎn)歡為AIDL的接口類型。

首先我們創(chuàng)建一個AIDL接口(Android Studio中通過New-> AIDL-> aidl file)

import com.ipc.www.Book;//必須顯式import

interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}

根據(jù)上面的代碼,AIDL中實現(xiàn)了兩個方法,獲取Book列表和添加Book,
這里需要注意的有兩點:
1、Book為實現(xiàn)了Parcelable的實體類。需要注意的是Book類必須import進來,無論是否在同一個包中。
2、在AIDL文件的接口方法中,如果參數(shù)為實現(xiàn)了Parcelable的接口類的話,參數(shù)必須標(biāo)注方向,in、out、inout。

Book.class

public class Book implements Parcelable {
    private int bookId;
    private String bookName;

    public Book(int bookId,String bookName){
        this.bookId = bookId;
        this.bookName = bookName;
    }

    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(bookId);
        parcel.writeString(bookName);
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookId=" + bookId +
                ", bookName='" + bookName + '\'' +
                '}';
    }
}

另外,如果AIDL文件中用到了自定義的Parcelable對象時,則必須創(chuàng)建和他同名的AIDL文件,并聲明為Parcelable類型,例如Book類,Book.aidl 代碼如下。

parcelable Book;

至此AIDL文件已經(jīng)創(chuàng)建完畢,接下來看服務(wù)端的實現(xiàn)。

public class BookManagerService extends Service {
    private static final String Tag = "BookManagerService";
    //bookList
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();

    // 創(chuàng)建Binder 實現(xiàn)IBookManager AIDL中的方法 并通過OnBind返回這個binder
    private Binder mBinder = new IBookManager.Stub() {
        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
            Log.i(Tag,mBookList.toString());
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

客戶端的實現(xiàn)。

public class AidlActivity extends AppCompatActivity {

    private static final String Tag = "AidlActivity";

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //將Binder 轉(zhuǎn)換為AIDL的接口類型 即可調(diào)用aidl中的方法
            IBookManager bookManager = IBookManager.Stub.asInterface(iBinder);
            try {
                //添加一本書
                Book book = new Book(1,"我是一本書");
                bookManager.addBook(book);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aidl);
        //綁定Service
        Intent intent = new Intent(this, BookManagerService.class);
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
    }
}

運行上述代碼,可以看到控制臺中成功輸出了我們添加的內(nèi)容(圖1)。


圖1

細(xì)心的小伙伴可能會問了,為什么mBookList使用CopyOnWriteArrayList而不用List呢?
這是因為CopyOnWriteArrayList支持高效率并發(fā)且是線程安全的,在AIDL中,難免會存在多線程同時訪問的情況,所以在AIDL的方法中就需要做線程同步,而使用CopyOnWriteArrayList恰恰為我們省去了這部分工作。

AIDL中傳輸數(shù)據(jù)都支持哪些類型呢?

1、基本數(shù)據(jù)類型;
2、String和CharSequence;
3、ArrayList,HashMap,且其中的每個元素必須能夠被AIDL支持。
4、實現(xiàn)了Parcelable的對象。
5、AIDL接口本身。

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

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

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