AIDL使用學習(一):基礎使用學習

weixin_34290000發表於2017-09-12

前言#

使用aidl已經很長時間了,在實際應用中主要是新建程式來做些可能佔用記憶體很高的操作,不僅可以降低主程式的記憶體佔用,而且服務程式崩潰不會影響主程式的執行,確實非常實用。

這一篇主要講講aidl的基礎用法。

正文#

AIDL:Android Interface Definition Language,即Android介面定義語言。

基礎概念就不多說了,AIDL主要是提供了跨程式通訊機制,android的底層通訊是使用了IPC通訊機制,AIDL就是在這個機制的基礎上提供了方便的使用方法,讓開發者自定義自己的服務程式。

下面就來寫一個簡單的demo,功能就是傳給Service一個bean,計算bean中的x,y相加的值,並返回:

1、首先,我們先把bean檔案寫好:

package com.lzp.aidlstudy.bean;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by li.zhipeng on 2017/4/25.
 * <p>
 * 測試用類
 */

public class TestBean implements Parcelable {

    private int x;

    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public static final Parcelable.Creator<TestBean> CREATOR = new Creator<TestBean>() {
        @Override
        public TestBean[] newArray(int size) {
            return new TestBean[size];
        }

        @Override
        public TestBean createFromParcel(Parcel in) {
            TestBean bean = new TestBean();
            bean.setX(in.readInt());
            bean.setY(in.readInt());
            return bean;
        }
    };

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(x);
        dest.writeInt(y);
    }
}

這裡的TestBean實現了序列化介面Parcelable,跨程式通訊的物件都要實現這個介面。

  1. 編寫我們的aidl檔案。我們建立一個aidl資料夾:


    5615762-ccdfa6db1672bb78
    這裡寫圖片描述

從圖中看到,我們建立了兩個aidl檔案,先看TestBean.aidl:

// 序列化TestBean,供跨程式使用
package com.lzp.aidlstudy.bean;
parcelable TestBean;

很簡單,就是定義TestBean要跨程式序列化,但是要注意兩點:

1、.aidl 檔名必須和類名一致。
2、在aidl資料夾中放到相同的包中。

如果以上兩點不滿足,就會報無法引入這個類的錯誤。

然後看我們的aidl服務檔案ITestInterface:

// aidl  定義實現的Service方法
package com.lzp.aidlstudy;

import com.lzp.aidlstudy.bean.TestBean;

interface ITestInterface {

    // 定義一個計算方法
    int getCalculateResult(in TestBean bean);

}

檔案中引入了TestBean,並且定義了getCalculateResult方法,方法的引數需要新增修飾符:

in :引數只能由客戶端傳遞給服務端,客戶端的物件不會因為服務端對傳參的修改而發生變動
out :服務端將會接收到那個物件的引數為空的物件,但是在服務端對接收到的空物件有任何修改之後客戶端將會同步變動。
inout 為定向 tag 的情況下,服務端將會接收到客戶端傳來物件的完整資訊,並且客戶端將會同步服務端對該物件的任何變動。

以上具體分析請參考部落格:http://blog.csdn.net/luoyanglizi/article/details/51958091

ok,我們服務代理也已經寫好了,那麼就可以建立我們的TestService了:

/**
 * Created by li.zhipeng on 2017/4/25.
 *
 *      跨程式服務類
 *
public class TestService extends Service {

    private final ITestInterface.Stub binder = new ITestInterface.Stub() {

        @Override
        public int getCalculateResult(TestBean bean) throws RemoteException {
            return bean.getX() + bean.getY();
        }
    };

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

我們去實現了剛才的ITestInterface的服務代理類中的getCalculateResult方法,這樣通過返回binder,就可以直接與TestService通訊了。

趕緊去註冊一下服務:

 <service
            android:name=".TestService"
            android:process=":test"></service>

我們給這個服務程式命名為:test,以冒號開頭,是命名規則,這個不要忘記。

那我們的功能就OK了,MainActivity就不貼出來了,點選繫結服務,在點選就彈出提示:

5615762-b5c40f4e9e2f820f
這裡寫圖片描述

總結#

ok,基礎使用就到這裡了,非常的簡單,然後實際上並非如此,我們啟動了某一個服務,裡面往往都是耗時操作,那麼就要通過Thread來處理複雜的耗時操作,然後通過Callback返回操作的結果,那麼下一篇我們就來解決這個問題。

demo下載地址

相關文章