Android中的IPC之使用Bundle

Android中的IPC方式

在Android中實現跨進程通信的方式有很多,具體的方式主要有以下幾種:
1. 使用Bundle
2. 使用文件共享
3. 使用Messenger
4. 使用AIDL
5. 使用ContentProvider
6. 使用Socket

以下是各種IPC方式的優缺點和適用場景,圖片源自《Android開發藝術探索》P121。

這裏寫圖片描述


爲什麼可以使用Bundle實現IPC

我們知道,Intent是Android程序中各組件之間進行交互的一種重要方式,它不僅可以指明當前組件想要執行的操作,還可以在不同的組件之間傳遞數據。

  • 利用Intent傳遞數據主要分兩種,基本類型數據和對象。
  • 但值得注意的是利用Intent來傳遞數據,它對要傳遞的數據類型是有要求的,我們傳輸的數據必須要能夠被序列化。
  • 我們知道基本類型是能夠被序列化的,那麼對象呢?Android中主要有兩種方式來實現對象序列化:Serilable接口和Parcelable接口。而Bundle爲什麼可以藉助Intent來實現IPC呢?因爲在Android中,有許多實現了Parcelable接口的類,如Bundle、Intent、Bitmap,同時List和Map也可序列化,前提是它們裏面的每個元素才能序列化。這就解釋了爲什麼我們可以利用Bundle來實現IPC了,同時也解釋了爲什麼Intent本身也可以攜帶基本數據進行數據傳遞。下面用實際的例子來展示利用Intent作爲載體傳遞基本數據,以及利用Intetn使用Bundle作爲載體來實現進行間通信的具體實現。

使用Bundle和Intent傳遞數據

  1. 利用Intent本身作爲載體傳遞基本類型數據

    • 實現思路:利用Intent中提供的一系統putExtra()方法的重載,把我們想要傳遞的數據暫存於Intent中,當要取數據的時候利用getXXXExtra()方法將數據從Intent中取出來。其中putExtra()方法接收兩個參數,第一個參數鍵,用於後面從Intent中取值,第二個參數纔是真正要傳遞的數據,getXXXExtra()方法根據要提取的數據的類型選擇不用的方法,例如傳遞是的字符串,則用getStringExtra()方法,若是布爾類型,則用getBooleanExtra()方法,依次類推,注:除了String類型的getStrignExtra()是隻傳入一個鍵值參數外,其他基本類型的方法都是需要輸入兩個參數的,第一個是鍵值,第二個是默認數據值(當按鍵值找不到對應的數據時,就回返回這個默認的值)。
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        String data1 = "Hello";
        Double data2 = 98.0;
        intent.putExtra("data1_key",data1);
        intent.putExtra("data2_key",data2);
        startActivity(intent);
  • 說明:在FirstActivity中傳遞一個字符串“Hello”和一個雙精度常數98.0。
    Intent在這裏的作用有兩個,其一是用於啓動從FirstActivity活動到SecondActivity活動 其二是作爲傳遞數據載體。
        Intent intent =  getIntent();
        String data1 = intent.getStringExtra("data1_key");
        Double data2 = intent.getDoubleExtra("data2_key",1);
  • 說明:在SecondActivity中先通過getIntent();方法獲得啓動SecondActivity活動的Intent的實例,然後利用getXXXExtra()方法來提取數據。

2. Intent結合Bundle作爲載體進行數據傳遞

  • 實現思路:把需要傳遞的數據都保存在Bundle對象中,然後將Bundle對象存放在Intent裏,提取數據時,先從Intent中取出Bundle,再從Bundle中逐一取出數據。
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        String data1 = "Hello";
        Double data2 = 98.0;
        Bundle bundle = new Bundle();
        bundle.putString("data1_key",data1);
        bundle.putDouble("data2_key",data2);
        intent.putExtras(bundle);
  • 說明:在FirstActivity中傳遞一個字符串“Hello”和一個雙精度常數98.0,利用putXXX(key
    value)方法將數據在於一個Bundle對象中,然後把Bundle對象放在Intent中。
        Intent intent =  getIntent();
        Bundle bundle = intent.getExtras();
        String data1 = bundle.getString("data1_key");
        Double data2 = bundle.getDouble("data2_key")
  • 說明:在SecondActivity中,先通過getIntent()方法獲取啓動SecondActivity的Intent實例,接着利用getExtras()方法從Intent中取出Bundle,然後再從Bundle對象利用getXXX(key)方法取出數據。

3. 使用Bundle解決活動被回收會失去臨時數據的問題
應用場景:應用中有一個活動A,用戶在活動A的基礎上啓動了活動B,活動A就會進入停止狀態,這時由於系統的內存不足,將活動A回收了,此時當用戶從活動B中按Back鍵返回活動A的時候,由於活動A已被回收,此時會重新創建一次(即此時活動A並不會執行onRestart()方法,而是執行onCreate()方法),那麼活動A中的臨時數據和狀態都會全沒了。

解決辦法:活動的onCreate()方法中有一個Bundle類型的參數,這個參數在一般情況下都是null的,但是如果在活動系統在回收之前有通過onSvaeInstanceState()方法的Bundle參數來保存數據的話,活動的onCreate()方法的Bundle參數就會帶有之前所保存的全部數據,我們只需要再通過相應的取值方法將數據取出就可以了。

1). 在活動A中重寫onSaveInstanceState()方法,利用該方法裏面攜帶的Bundle參數,來存入存放臨時的數據。

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String temData = "Something you want to save";
        outState.putString("data_key", temData);
    }

說明:利用putString(key,value)方法將一個字符串在於Bundle參數的outState中。

2). 在活動A的onCreate()方法中取出數據。

    protected void onCreate(Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null){
            String temData = savedInstanceState.getString("data_key");
        }
        ...

說明:利用getString(key)方法從Bundle參數的saveInstaceState中取出相應的數據。

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