天天看點

IPC機制之三:IPC方式(Bundle、檔案共享、Messenger)

跨程序通信的方式

1.通過Intent中附加extras來傳遞資訊。

2.通過共享檔案的方式來共享資料。

3.通過Binder方式來跨程序通信。

4.ContentProvider本身就是支援跨程序通信的。

5.此外網絡通信也是可以實作傳遞資料的,是以Socket也可以實作IPC。

.

.

使用Bundle

四大元件中有三大元件(Activity、Service、Receiver)是支援在Intent中傳遞Bundle資料的。Bundle實作了Parcelable接口,是以它可以友善的在不同程序間傳輸。在Bundle中添加的資料可以是基本資料類型、實作了Parcelable或Serializable接口的對象以及Android支援的特殊對象。

.

.

使用檔案共享

共享檔案是一種不錯的程序間通信方式,兩個程序通過讀/寫同一個檔案來進行交換資料。由于Android系統是基于Linux的,使得其并發讀/寫檔案可以沒有任何限制地進行,甚至兩個線程同時對同一個檔案進行寫操作都是被充許的,盡管這可能出問題。除了可以交換一些文本資訊外,還可以序列化一個對象到檔案系統中的同時從另一個程序中恢複這個對象。

注意:如果并發讀/寫,我們讀取出來的資料可能不是最新的,如果是并發寫的話那就更嚴重了,是以我們要盡量避免并發寫這種情況的發生或者考慮使用線程同步來限制多個線程的寫操作。檔案共享方式适合在對資料同步要求不高的情況的程序之間進行通信,并且要妥善處理并發讀/寫的問題。

SharedPreferences是Android中輕量級的存儲方案,通過鍵值對的方來存儲資料。從本質來說,SharedPreferences也是屬于檔案的一種,但是系統對于它的讀/寫有一定的緩存政策,即在記憶體中有一份SharedPreferences檔案的緩存,是以在多程序模式下,系統對它的讀/寫變得不可靠,面對高并發的讀/寫通路有很大幾率會丢失資料。不建議在程序間通信中使用SharedPreferences。

.

.

使用Messenger

通過使用Messenger傳遞Message對象,在Message中放入我們需要傳遞的資料。就可以輕松實作資料的程序間傳遞。Messenger是一種輕量級的IPC方案,其底層實作是AIDL。其在源代碼中的構造方法中可得知。

.

它一次隻能處理一個請求,是以在服務端我們無需考慮線程同步的問題。

實作Messenger有如下幾個步驟,分為服務端和用戶端。

1.服務端

首先需要建立一個Service來處理用戶端的連接配接請求,同時建立一個Handler并通過它來建立一個Messenger對象,然後在Service的onBind中傳回這個Messenger對象底層的Binder對象。

2.用戶端

首先需要綁定服務端Service,綁定成功後用服務端傳回的IBinder對象建立一個Messenger,通過這個Messenger就可以向服務端發送消息了,發送消息的類型是Message。如果需要服務端回複用戶端,用戶端就和服務端一樣,建立一個Handler并建立一個Messenger對象,使用在發送給服務端的Message.replyTo指定為用戶端的Messenger對象。

Message和Messenger都是實作了Parcelable接口的,是以可以跨程序傳輸。Message中能使用的載體隻有what,age1,age2,Bundle以及replyTo。另外還有object,但這個參數對于在同一個程序中是很實用的,但是在多程序中(2.2以前是不支援跨程序傳輸的,2.2以後也是也隻是支援系統實作了Parcelable的對象)。

下面是示範代碼:

package com.thh.ipcdemo2.messenger;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.thh.ipcdemo2.R;

public class MessengerActivity extends AppCompatActivity {

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("thhi","[MessengerActivity ServiceConnection onServiceConnected]");
            Messenger messenger = new Messenger(service);
            Message message = Message.obtain(null, MessengerService.MSG_FROM_CLIENT);
            Bundle bundle = new Bundle();
            bundle.putString("msg","你好! 我是用戶端");
            message.setData(bundle);
            message.replyTo = mMessenger;
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("thhi","[MessengerActivity ServiceConnection onServiceDisconnected]");
        }
    };

    private static class MessengerHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MessengerService.MSG_FROM_SERVICE:
                    String content = msg.getData().getString("msg");
                    Log.i("thhi","[MessengerActivity MessengerHandler handleMessage]"+content);
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    private Messenger mMessenger = new Messenger(new MessengerHandler());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);

        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }
}
           
package com.thh.ipcdemo2.messenger;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by TangHui on 2015/10/14.
 */
public class MessengerService extends Service {

    public static final int MSG_FROM_CLIENT = ;
    public static final int MSG_FROM_SERVICE = ;

    private class MessageHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            Log.i("thhi","[MessengerService MessageHandler handleMessage]");
            switch (msg.what){
                case MSG_FROM_CLIENT:
                    String content = msg.getData().getString("msg");
                    Log.i("thhi","[MessengerService MessageHandler handleMessage] content:"+content);

                    Messenger replyTo = msg.replyTo;
                    Message message = Message.obtain(null, MSG_FROM_SERVICE);
                    Bundle bundle = new Bundle();
                    bundle.putString("msg","這是服務端,已經成功收到你的消息!");
                    message.setData(bundle);
                    try {
                        replyTo.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    private final Messenger mMessenger = new Messenger(new MessageHandler());

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("thhi","[MessengerService onBind]");
        return mMessenger.getBinder();
    }
}
           

繼續閱讀