1. android 中多進(jìn)程模式
android 進(jìn)程間通信的方式
1.Intent
2.文件共享
3.AIDL
4.Messenger
5.ContentProvider
6.RemoteViews
7.socket
1.1 多進(jìn)程的開啟方式
android中使用多進(jìn)程只有一種方法,就是給四大組件在AndroidMenifest 中指定android:processs屬性,那么問題來了,我們常常會(huì)使用兩種指定方式:
android:process=":remote"
android:process="com.android.test"
這兩種方式有何區(qū)別乏悄?
- 1.":"的含義是要在進(jìn)程名“remote”前加上包名的陨晶,加":"是一種簡寫
- ":"開頭的進(jìn)程屬于當(dāng)前應(yīng)用的私有進(jìn)程泻蚊,其他應(yīng)用的組件不可以和它跑在同一個(gè)進(jìn)程中栅哀。不以":"命名的進(jìn)程屬于全局進(jìn)程,其他應(yīng)用通過ShareUID 方式可以和它跑在同一個(gè)進(jìn)程中
android 系統(tǒng)會(huì)為每個(gè)應(yīng)用分配一個(gè)唯一的UID,相同UID的應(yīng)該可以共享數(shù)據(jù)而账,如果兩個(gè)應(yīng)用通過相同ShareUID跑在同一個(gè)進(jìn)程中胰坟,還需要有相同簽名才可以相互訪問私有數(shù)據(jù),比如 data目錄泞辐、組件信息等笔横,跑在同一進(jìn)程中竞滓,當(dāng)然可以共享內(nèi)存數(shù)據(jù)。
所有運(yùn)行在不同進(jìn)程中的四大組件吹缔,如果他們需要通過內(nèi)存來共享數(shù)據(jù)商佑,都會(huì)失敗
一般來說,多進(jìn)程會(huì)照成如下的一些問題:
1.靜態(tài)成員和單例模式完全失效
2.線程同步機(jī)制失效
3.SharePreferences 的可靠性下降
4.Application 可能多次創(chuàng)建
2. IPC中一些基礎(chǔ)概念
2.1Seriailzable 接口
Serializable 是Java 提供的一個(gè)序列化接口厢塘,是一個(gè)空接口茶没,為對象提供標(biāo)準(zhǔn)的序列化和反序列化操作,
SerialVersionUID 需指定晚碾,否則可能會(huì)導(dǎo)致反序列化失敗
2.2 Parcelable 接口
Parcelable接口也是一個(gè)接口抓半,只要實(shí)現(xiàn)這個(gè)接口,這個(gè)類對象就可以實(shí)現(xiàn)序列化并通過Intent格嘁、Binder傳遞
3.下面主要分析下使用AIDL文件進(jìn)行進(jìn)程間通信
- 舉一個(gè)使用aidl 進(jìn)行IPC通信的例子
MainActivity 和PersonService 分屬于兩個(gè)進(jìn)程笛求,我們用aidl 進(jìn)行雙向通信
完成 MainActivity創(chuàng)建person對象傳到service 中進(jìn)行保存,activity主動(dòng)向service
拿所有數(shù)據(jù)糕簿,service以集合的方式返回所有數(shù)據(jù)
我們定義的IPersonService.aidl (aidl 文件路徑要和package定義的包名路勁下)
// IPersonService.aidl
package com.prsioner.androidaidldemo;
// Declare any non-default types here with import statements
import com.prsioner.androidaidldemo.Person;
interface IPersonService {
void savePersonInfo(in Person person);
List<Person> getAllPerson();
}
Person.aidl
// Person.aidl
package com.prsioner.androidaidldemo;
// Declare any non-default types here with import statements
parcelable Person;
編譯后自動(dòng)生成的接口類IPersonService 在build/generated/source/aidl/....
activity 作為client 端通過bindService啟動(dòng)service進(jìn)程探入,傳入一個(gè)ServiceConnection 來接受服務(wù)端在
客戶端的引用 iService
IPersonService iService;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(tag,"onServiceConnected");
iService = IPersonService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(tag,"onServiceDisconnected()");
}
};
activity 發(fā)送數(shù)據(jù)和接受數(shù)據(jù)
iService.savePersonInfo(person);
List<Person> personList = iService.getAllPerson();
service 服務(wù)端的部分代碼:
public IBinder onBind(Intent intent) {
return iBinder;
}
private final IPersonService.Stub iBinder = new IPersonService.Stub(){
@Override
public void savePersonInfo(Person person) throws RemoteException {
if(person !=null){
personList.add(person);
}
}
@Override
public List<Person> getAllPerson() throws RemoteException {
return personList;
}
};
我們來看aidl 完成通信的具體實(shí)現(xiàn)過程
package com.prsioner.androidaidldemo;
public interface IPersonService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.prsioner.androidaidldemo.IPersonService
{
private static final java.lang.String DESCRIPTOR = "com.prsioner.androidaidldemo.IPersonService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.prsioner.androidaidldemo.IPersonService interface,
* generating a proxy if needed.
*/
public static com.prsioner.androidaidldemo.IPersonService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.prsioner.androidaidldemo.IPersonService))) {
return ((com.prsioner.androidaidldemo.IPersonService)iin);
}
return new com.prsioner.androidaidldemo.IPersonService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_savePersonInfo:
{
data.enforceInterface(descriptor);
com.prsioner.androidaidldemo.Person _arg0;
if ((0!=data.readInt())) {
_arg0 = com.prsioner.androidaidldemo.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.savePersonInfo(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getAllPerson:
{
data.enforceInterface(descriptor);
java.util.List<com.prsioner.androidaidldemo.Person> _result = this.getAllPerson();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.prsioner.androidaidldemo.IPersonService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void savePersonInfo(com.prsioner.androidaidldemo.Person person) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_savePersonInfo, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.util.List<com.prsioner.androidaidldemo.Person> getAllPerson() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.prsioner.androidaidldemo.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAllPerson, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.prsioner.androidaidldemo.Person.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_savePersonInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getAllPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void savePersonInfo(com.prsioner.androidaidldemo.Person person) throws android.os.RemoteException;
public java.util.List<com.prsioner.androidaidldemo.Person> getAllPerson() throws android.os.RemoteException;
}
IInterface接口: 所有用Binder傳輸數(shù)據(jù)的接口都必須繼承這個(gè)接口
Stub: 繼承自Binder 實(shí)現(xiàn)我們定義的aidl類接口IPersonService,其實(shí)就是作為服務(wù)端的一個(gè)binder對象
Stub 中有一個(gè)DESCRIPTOR,它是Binder的唯一標(biāo)識,其中兩個(gè)int常量是用來標(biāo)識我們在接口中定義的方法的
asInterface()方法 用于將服務(wù)端的Binder對象轉(zhuǎn)換為客戶端所需要的接口對象,該過程區(qū)分進(jìn)程懂诗,如果進(jìn)程一樣新症,
就返回服務(wù)端Stub對象本身,否則呢就返回封裝后的Stub.Proxy對象(服務(wù)端在客戶度的代理對象)
onTransact() 方法 是運(yùn)行在服務(wù)端的Binder線程中的响禽,當(dāng)客戶端發(fā)起遠(yuǎn)程請求后,在底層封裝后會(huì)交由此方法來處理荚醒。
通過code來區(qū)分客戶端請求的方法
Proxy代理對象類我們主要看一下我們定義的方法savePersonInfo()和getAllPerson()就可以了芋类,這兩個(gè)方法都是運(yùn)行在客戶端,
當(dāng)客戶端發(fā)起遠(yuǎn)程請求時(shí)界阁,_data會(huì)寫入?yún)?shù)侯繁,然后調(diào)用transact方法發(fā)起RPC(遠(yuǎn)程過程調(diào)用)請求,同時(shí)掛起當(dāng)前線程泡躯,
然后服務(wù)端的onTransact方法就會(huì)被調(diào)起贮竟,直到RPC過程返回后,當(dāng)前線程繼續(xù)執(zhí)行较剃,并從_reply取出返回值(如果有的話)咕别,并返回結(jié)果
最后附上示例代碼地址:https://github.com/prsioner/androidAIDLDemo