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

Android 手写Binder 教你理解android中的进程间通信

2016-01-27 15:35 471 查看
关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难。今天就教你如何从 app层面来理解好Binder。

其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介。

AIDL就是我们理解Binder 最好的事例。

我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码。实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件

是不会被打包进去的,也就是说aidl文件 实际上 就是我们用来 生成 实际binder代码用的。所以 我们只要能够分析好,ide自动帮我们生成的

代码,就可以自己手写binder,从而在app层面上真正理解binder的用法和含义 以及原理。

首先我先来定义一个实体类:Person.java

package com.example.administrator.writebindercodeexample;

import android.os.Parcel;
import android.os.Parcelable;

/**
* Created by Administrator on 2016/1/27.
*/
public class Person implements Parcelable {

private String name;

public void setName(String name) {
this.name = name;
}

public void setGender(int gender) {
this.gender = gender;
}

public int getGender() {
return gender;
}

public String getName() {
return name;
}

private int gender;

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.gender);
}

public Person() {
}

protected Person(Parcel in) {
this.name = in.readString();
this.gender = in.readInt();
}

public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
public Person createFromParcel(Parcel source) {
return new Person(source);
}

public Person[] newArray(int size) {
return new Person[size];
}
};
}


注意看 我们这个person 类 是实现了android自带的序列化接口的,所以 如果你要在aidl里使用这个类,那你必须要额外在aidl里生命下 这个类。

// Person.aidl.aidl
package com.example.administrator.writebindercodeexample;

// Declare any non-default types here with import statements
parcelable Person;


// IPersonManager.aidl
package com.example.administrator.writebindercodeexample;

// Declare any non-default types here with import statements
import com.example.administrator.writebindercodeexample.Person;
interface IPersonManager {
List<Person> getPersonList();
//关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说
void addPerson(in Person person);
}


好,然后给你们看一下 文件结构:

package com.example.administrator.writebindercodeexample;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

/**
* Created by Administrator on 2016/1/27.
*/
public abstract class DogManagerImpl extends Binder implements IDogManager {

public DogManagerImpl() {
this.attachInterface(this, DESCRIPTOR);
}

public static com.example.administrator.writebindercodeexample.IDogManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//如果是同1个进程,也就是说进程内通信的话 我们就返回括号内里的对象
if (((iin != null) && (iin instanceof com.example.administrator.writebindercodeexample.IDogManager))) {
return ((com.example.administrator.writebindercodeexample.IDogManager) iin);
}
//如果不是同一进程,是2个进程之间相互通信,那我们就得返回这个Stub.Proxy 看上去叫Stub 代理的对象了
return new com.example.administrator.writebindercodeexample.DogManagerImpl.Proxy(obj);
}

@Override
public IBinder asBinder() {
return this;
}

@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getDogList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.example.administrator.writebindercodeexample.Dog> _result = this.getDogList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addDog: {
data.enforceInterface(DESCRIPTOR);
com.example.administrator.writebindercodeexample.Dog _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.administrator.writebindercodeexample.Dog.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addDog(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy extends DogManagerImpl {
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 java.util.List<com.example.administrator.writebindercodeexample.Dog> getDogList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.example.administrator.writebindercodeexample.Dog> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(DogManagerImpl.TRANSACTION_getDogList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.example.administrator.writebindercodeexample.Dog.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

@Override
public void addDog(com.example.administrator.writebindercodeexample.Dog dog) 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 ((dog != null)) {
_data.writeInt(1);
dog.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(DogManagerImpl.TRANSACTION_addDog, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}

}


View Code

到这,我们的手写binder 就完成了,然后看看 service 以及客户端 怎么调用。

先看service:

package com.example.administrator.writebindercodeexample;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class RemoteService extends Service {

private List<Dog> mDogsList = new ArrayList<Dog>();

private final DogManagerImpl mBinder = new DogManagerImpl() {
@Override
public List<Dog> getDogList() throws RemoteException {
return mDogsList;
}

@Override
public void addDog(Dog dog) throws RemoteException {
mDogsList.add(dog);
}
};

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


然后看看 启动如何在客户端bind 这个service:

private IDogManager mService;

private ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = DogManagerImpl.asInterface(service);

}

@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};


到这 就基本写完了,手写binder的好处就是 你可以自己在binder方法里 写一些log,能够更加深刻的认识到 Binder 作为 进程间通信 媒介的重要作用以及原理。

熟悉以后,还是用aidl 的方法 自动生成代码 最好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: