爲什麼要用AIDL

說到AIDL,每次就配套一個單詞就是IPC,到底是怎麼一回事,這事得從多進程說起。
有一天,我們寫了一個類,類裏面有一個靜態變量。就像下面這樣

public class UserBean { 

    public  static  int userCount=0;

}

原本的需求是這樣的,通過這個User類的一個靜態值,來全局共享一些用戶信息,提供給A和B顯示用,而這A和B是在兩個獨立的進程中(非線程)的,同時要求對這個數據有讀寫的能力。
關於如何開啓多進程,估計很多程序是用不到的,因爲他的場景不是很廣泛,我們有可能是採用別的方案就避免掉了,例如廣播之類的。
開啓多進程的方法就是在我們的xml配置文件加多process屬性,如下:

   <activity
        android:name=".activity.Test2Activity"
        android:process=".newProcess1" />

    <service
        android:name=".service.MyDemoService"
        android:enabled="true"
        android:exported="true"
        android:process=":newProcess2" />

是不是很簡單的感覺就可以開多進程了?

這裏有一點需要注意的就是我們在名字前面的符號是什麼,一個是“ : ”,另外一個是“.
兩者導致的就是進程的名字不一樣而已,同時如果以“:”開頭,表示該進程爲當前應用私有,和其他的組件是不會跑在同一個進程中的。後者是全局進程,可以和別的組件跑在同個進程,然後進行數據共享的。具體的內容以後再補充吧,說多有感覺跑遠了。

現在假設我們先啓動了A進程,然後設置值爲1,接着啓動B進程,打印數據,理論是等於1纔對。

public class A{

    UserBean.userCount=1;
}

public class  B{


       Log.e(TAG, "count="+UserBean.userCount);
}

但我們居然發現打印是0, 這可壞了,這是爲啥呢?
我們很當然的要懷疑起這個多進程到底怎麼了?
簡單的說就是,在安卓上,多進程就代表了”同時運行多個同樣的app“
既然是兩個同時運行的A和B,那兩者想讓就互補影響了。
不知有沒映像,以前在諾基亞的塞班S60時代手機上有QQ共存版 ,同時運行多個QQ,每個QQ收到的數據是互不影響的,多進程大抵就是這種樣子。
多進程帶來的問題當然不知這些啦,我們的單例模式,線程同步等都顯然形同虛設了,但需求還在那,我們需要把這事幹了啊,那怎麼辦呢?
我們的不同進程要進行溝通解決啦,所以就有了這樣那樣的進程間進行通訊的機制(IPC)。

IPC有哪些?

能做進程間通訊的常見的有基於Binder的messenger,AIDL和Socket。據聞基於binder的效率最高,具體怎麼比出來的,我也沒看過。另外還有SharedPreferences,ContentProvider,Bundle等

AIDL

我們先寫一個接口文件,用來給別的進程調用用的,這裏我們提供一對get/set方法。

// UserManagerInterface.aidl
interface UserManagerInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

    int getUserCount();

    void setUserCount( in int n);

}

接着我們谷歌說的要求,寫這麼個獨立的類,裏面只有下面那個

// UserBean.aidl
package com.example.sanjay.myapplication.aidl;

parcelable UserBean;

最後我們再寫一個簡單的UserBean類

public class UserBean implements Parcelable {

    public  static  int UserCount=0;

    private  String userName;


    protected UserBean(Parcel in) {
        userName = in.readString();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(userName);
    }
}

整個的結構就這樣
這裏寫圖片描述

然後爲了我們的演示方便,我們在service裏面加多一個類,如下,很簡單,沒什麼特別要說的

public class AidlService extends Service {  

    private final UserManagerInterface.Stub mBidnerStub = new UserManagerInterface.Stub() {

        @Override
        public int getUserCount() throws RemoteException {
            return UserBean.UserCount;
        }

        @Override
        public void setUserCount(int n) throws RemoteException {
            UserBean.UserCount = n;
        }
    };

    public AidlService() {

    }

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

接着在我們的其中一個寫下面的內容

public class MainActivity extends BaseActivity {

    private static final String TAG = MainActivity.class.getSimpleName();     

    UserManagerInterface mService;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.e(TAG, "connect service");
            mService = UserManagerInterface.Stub.asInterface(service);
            try {
                Log.e(TAG, "curUserCount=" + mService.getUserCount());
                mService.setUserCount(2);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            Log.e(TAG, "disconnect service");
            mService = null;
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        Intent intent = new Intent(this, AidlService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);        
    }

}

好了,核心的內容就這麼點啦。基本都配置好了。
現在我們就可以做跨進程的通訊工作了。
由於時間限制,今天先寫到這裏,明天再補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章