Android中常见IPC方法总结

IPC (Interprocess communication)跨进程通信,是指在两个进程之间交换数据的过程。多进程通信一般分为两种情况。第一种,一个应用因为自身的需要采用多进程实现,比如某些模块由于特殊原因需要运行在单独的进程中。第二种情况,当前应用需要获得其它应用的数据,由于是两个应用,所以必须采用跨进程的方式。下面就对常用的IPC方法做一个总结。

使用Bundle

Activity,Service,Receiver都是支持在Intent中传递Bundle的,由于Bundle实现了Parcelable接口,所以他可以在不同进程间传输。我们可以在Bundle中附加数据,并通过Intent传送出去。当然,传送的数据必须是能够被序列化的。关于Android中序列化的知识可以参考http://blog.csdn.net/l664675249/article/details/49403333

使用文件共享

A进程把数据写入文件,B进程通过读取这个文件来获得数据。但这这种方法有一个问题就是并发读/写问题。有一个特例,SharedPreferences是Android中提供的轻量级存储方案,底层采用XML实现。但是对于他的读写有一定的缓存策略,因此不建议在进程间通信中使用他。

举例

在MainActivity的onResume中序列化一个对象到sd卡,然后再SecondActivity的onResume中反序列化。关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//MainActivity
  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();
     }

使用Messenger

Messenger是一种轻量级的IPC方案,他的底层实现时AIDL。他是以串行的方式处理客户端发来的消息的,一次处理一个请求,因此我们不考虑线程同步问题。

下面是一个例子,客户端向服务端发送一个请求,服务的接到请求后向客户端返回一个消息,Service是注册在另外一个进程中的。

MessengerService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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);
     }
}

MessengerActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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();
     }
}

注:
Service

  • Service中有一个Handler,用来处理Client发来的消息,并在Handler中新建一个Messenger client = msg.replyTo来向客户端返回消息。
  • 在onBind中返回他里面的Binder对象

Client

  • 为了接收服务端的消息,客户端也需要准备一个接收消息的Messenger和Handler。
  • msg.replyTo = mGetReplyMessenger,当客户端发送消息的时候,需要把接收服务端回复的Messenger通过Message的replyTo参数传给服务端。

AIDL

Messenger以串行的方式处理客户端发来的消息的,一次处理一个请求,如果有大量的并发请求,那么用Messenger就不合适了,需要用AIDL。关于AIDL的讲解请参考http://blog.csdn.net/l664675249/article/details/50649676

ContentProvider

ContentProvider是Android中专门用于应用间进行数据共享的方式。详细示例请阅读书本P93.

Socket

实现思路,首先在远程Service建立一个TCP服务,然后在主界面中链接TCP服务,连接上后就可以给服务端发消息,服务端随机会随机回应一句话。关于Socket的讲解已经很多了,这里就不在赘述。

总结

IPC方式的优缺点和适用场景

Android中常见IPC方法总结_第1张图片

欢迎转载,转载请注明出处http://blog.csdn.net/l664675249/article/details/50654926

转载请注明:Android开发中文站 » Android中常见IPC方法总结

你可能感兴趣的:(Android)