您的位置:首页 > 移动开发 > Android开发

【Android】IPC机制(二)

2016-04-12 11:59 429 查看

Android中的IPC方式

1.使用Bundle

四大组件中的三大组件都支持在Intent中传递Bundle数据,由于Bundle接口实现了Parcelable接口,可以方便地在不同进程之间传输,传输的数据必须可以序列化,如基本数据类型、实现了Parcelable接口的对象,实现了Serialiable接口的对象等。

2.使用文件共享

适合用在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读/写问题。SharedPreferences也属于文件的一种,但是在内存中会有一份SharedPreferences文件的缓存,在多线程模式下就变得非常不可靠,因此不建议在进程间通信使用SharedPreferences。

3.使用Message

Message底层封装了AIDL。

使用步骤:

1)服务端进程。

在服务端创建一个Service来处理客户端的连接请求。

首先,创建一个Handle来处理客户端发送过来的消息,然后,通过这个Handle对象来创建Messenger对象,最后,在Service的onBind()方法中返回Messenger对象底层的Binder。

如果需要回应客户端,则通过msg的replyTo属性获得客户端的Messenger对象来发送Message。

private static class MessagerHandle extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("receive msg from Client:" + msg.getData().getString("msg"));
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("reply","嗯,你的消息我已收到,稍后会回复你");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}

private final Messenger messenger = new Messenger(new MessagerHandle());

@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}


2)客户端

绑定Service,根据服务端返回的binder对象,创建Messenger对象,并使用Messenger对象向服务端发送消息,如果客户端需要接收服务端发送的消息,也需要创建一个Handler来处理消息,并通过这个Handler对象创建一个Messenger,最后需要把接收服务端回复的Messager对象作为Message.replyTo参数传递给服务端。

private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("msg", "这是从客户端发送来的消息");
msg.setData(bundle);
msg.replyTo = clientMessenger;
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

Intent intent = new Intent(this, MessagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
private Messenger clientMessenger = new Messenger(new ClientHandler());

private static class ClientHandler extends android.os.Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("这是服务端的回复:" + msg.getData().getString("reply"));
}
}


4.使用AIDL

AIDL文件所支持的数据类型:

a.基本数据类型(int,long,char,boolean,double等);

b.String和CharSequence;

c.List:只支持ArrayList,里面每一个元素都必须能被AIDL文件支持;

d.Map:只支持HashMap,里面每一个元素都必须都能被AIDL文件支持,包括key,value

e.Parcelable:所有实现了Parcelable接口的对象;

f.AIDL:所有的AIDL接口本身也可以在AIDL文件中使用;

在AIDL文件中用到的自定义Parcelable对象必须新建一个和它同名的aidl文件

其内容如下:

package com.example.administrator.aidltest;
parcelable Book;


自定义Parcelable对象需要显式导入到AIDL接口中

AIDL中除了基本类型的参数,其它数据类型的参数必须标上方向in,out,inout

AIDL无法使用普通接口,所以AIDL使用接口也必须创建成AIDL文件。

1)服务端实现:

创建Service供客户端连接,在Service中实现AIDL接口并在onBind方法中返回binder对象

public class AIDLService extends Service {
public AIDLService() {
}

private CopyOnWriteArrayList<Book> mList = new CopyOnWriteArrayList<>();

@Override
public void onCreate() {
super.onCreate();
mList.add(new Book(1, "Android开发艺术探索"));
mList.add(new Book(2,"Android群英传"));
}

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

private Binder binder = new IBookManager.Stub(){

@Override
public void addBook(Book book) throws RemoteException {
mList.add(book);
}

@Override
public List<Book> getBookList() throws RemoteException {
return mList;
}
};

}


2)客户端实现:

绑定Service,获取接口对象

Intent intent = new Intent(this, AIDLService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);

private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List<Book> list = bookManager.getBookList();
for (Book book : list) {
System.out.println("bookid:" + book.bookId + ",bookname:" + book.bookName);
}
Book book = new Book(3,"Android源码设计模式解析与实战");
bookManager.addBook(book);
List<Book> newList = bookManager.getBookList();
for (Book allbook : newList) {
System.out.println("bookid:" + allbook.bookId + ",bookname:" + allbook.bookName);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}


5.使用ContentProvider

6.使用Socket

不能在主线程中访问网络,在Android4.0以上的设备中会抛出android.os.NetworkOnMainThreadException,而且网络操作很可能是耗时的,放在主线程也会影响程序的响应效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android