您的位置:首页 > 其它

二、IPC机制续(IPC方式)

2016-03-11 11:40 337 查看
IPC机制

具体方式有很多,比如可以在Intent中附加Extra来传递信息,或者通过共享文件的方式来共享数据,还可以采用Binder方式来跨进程通信,另外,Content Provider天生就是支持跨进程访问的,因此,我们也可以使用它来进行IPC,另外通过网络通信也是可以实现数据传递的,所以Socket也可以实现IPC。

1.使用Bundle

由于Bundle实现了Parcelable接口,所以它可以方便地在不同进程间传输。

除了直接传递数据这种典型的使用场景,他还有一种特殊的使用场景,如A进程正在进行计算,计算完成之后需要把结果传递给B进程,但是这个结果不支持放入Bundle中,那么可以这样考虑,A中,通过Intent启动B进程的一个Service组件(如IntentService),让Service进行后台计算,计算完毕之后,再启动B进程中真正想要启动的组件由于Service也在B进程中,所以目标组件就可以直接获取结果。

findViewById(R.id. button).setOnClickListener( new OnClickListener() {

@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity. this, SecondActivity.class);
User user = new User(0, "jake", true);
user. book = new Book();
intent.putExtra( "extra_user", (Serializable) user);
startActivity( intent);
}
});


2.使用文件共享

两个进程通过读写同一个文化夹来交换数据,比如A进程把数据写进文件,B进程通过读取这个文件来获取数据。Linux使得并发读写文件可以没有限制,甚至两个线程同时对一个文件进行读写都是运行的。

希望在ManActivity中的onResume中序列化一个User对象到SDk卡上面的一个文件里面,在SecondActivity的onResume中去反序列化。

MainActivity:onResume执行下面的方法

private void persistToFile() {

new Thread( new Runnable() {

@Override

public void run() {

User user = new User(1, “hello world”, false);

File dir = new File(MyConstants. CHAPTER_2_PATH);

if (! dir.exists()) {

dir.mkdirs();

}

File cachedFile = new File(MyConstants. CACHE_FILE_PATH );

ObjectOutputStream objectOutputStream = null;

try {

objectOutputStream = new ObjectOutputStream(

new FileOutputStream(cachedFile));

objectOutputStream.writeObject( user);

Log. d(TAG, “persist user:” + user);

} catch (IOException e) {

e.printStackTrace();

} finally {

MyUtils. close(objectOutputStream);

}

}

}).start();

}

SecondActivity中取:

private void recoverFromFile() {

new Thread(new Runnable() {

@Override
public void run() {
User user = null;
File cachedFile = new File(MyConstants. CACHE_FILE_PATH);
if ( cachedFile.exists()) {
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(
new FileInputStream( cachedFile));
user = (User) objectInputStream.readObject();
Log. d(TAG, "recover user:" + user);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
MyUtils. close(objectInputStream);
}
}
}
}).start();
}


当然这种不支持并发,如果想要并发,需要使用线程同步机制来解决。SharePreferences是个特例,通过键值对来存储数据,底层采用xml来存储键值对,位置在/data/data/packagename/shared_prefs目录下面,从本质来说SharePreferences也属于文件的一种,但是由于系统对它的读写有一定的缓存策略,即在内存里面有一份SharePreferences文件的缓存,因此在多进程模式下,系统对他的读写变得不可靠,当面对高并发的读写访问就有很大几率丢失数据,因此不建议进程间通信使用SP。

3.使用Messenger

Messenger是一种轻量级的IPC方案,它的底层实现是AIDL。从构造方法可以很明显的看出AIDL的痕迹。

public Messenger(Handler target) {

mTarget = target.getIMessenger();

}

public Messenger(IBinder target) {

mTarget = IMessenger.Stub.asInterface(target);

}

Messenger的使用方法很简单,它对AIDL做了封装,使得我们可以更简单地进行线程间通信,同时由于它一次处理一个请求,因此在服务端我们不用考虑线程同步的问题,这个是因为服务端不存在并发执行的情况。

步骤:

1.服务端进程,首先我们要创建一个Service来处理客户端的请求,同时创建一个Handler并通过它来创建一个Messenger对象,在Service的onBind里面返回这个Messenger对象底层的Binder即可。

2.客户端进程,首先要绑定服务端的Service,绑定成功之后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送消息了发送消息类型为Message对象。

如果要服务端能够回应客户端,就和服务端一样,需要创建一个Handler并创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。

服务端:

public class MessengerService extends Service {

private static final String TAG = “MessengerService”;

private static class MessengerHandler extends Handler {

@Override

public void handleMessage(Message msg) {

switch ( msg. what) {

case MyConstants. MSG_FROM_CLIENT:

Log. i(TAG, “receive msg from Client:” + msg.getData().getString( “msg”));

Messenger client = msg. replyTo;

Message relpyMessage = Message. obtain(null, MyConstants.MSG_FROM_SERVICE );

Bundle bundle = new Bundle();

bundle.putString( “reply”, “嗯,你的消息我已经收到,稍后会回复你。” );

relpyMessage.setData( bundle);

try {

client. send(relpyMessage);

} catch (RemoteException e) {

e.printStackTrace();

}

break;

default:

super.handleMessage( msg);

}

}

}

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

@Override

public IBinder onBind(Intent intent) {

return mMessenger.getBinder();

}

@Override

public void onCreate() {

super.onCreate();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

return super.onStartCommand( intent, flags, startId);

}

}

客户端:

public class MessengerActivity extends Activity {

private static final String TAG = “MessengerActivity”;

private Messenger mService;

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

private static class MessengerHandler extends Handler {

@Override

public void handleMessage(Message msg) {

switch ( msg. what) {

case MyConstants. MSG_FROM_SERVICE:

Log. i(TAG, “receive msg from Service:” + msg.getData().getString( “reply”));

break;

default:

super.handleMessage( msg);

}

}

}

private ServiceConnection mConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName className, IBinder service) {

mService = new Messenger( service);

Log. d(TAG, “bind service”);

Message msg = Message. obtain(null, MyConstants.MSG_FROM_CLIENT );

Bundle data = new Bundle();

data.putString( “msg”, “hello, this is client.”);

msg.setData( data);

msg. replyTo = mGetReplyMessenger;

try {

mService.send( msg);

} catch (RemoteException e) {

e.printStackTrace();

}

}

public void onServiceDisconnected(ComponentName className) {

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate( savedInstanceState);

setContentView(R.layout. activity_messenger);

Intent intent = new Intent( “com.ryg.MessengerService.launch”);

bindService( intent, mConnection, Context. BIND_AUTO_CREATE);

}

@Override

protected void onDestroy() {

unbindService( mConnection);

super.onDestroy();

}

}

Mainfest里面:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: