这篇文章?我觉得写进程间通信,写Binder的介绍,写的非常的好,读了以后对binder有了更深的理解。不过我觉得这篇文章写Binder,写的还是比较虚,都是一些跨进程啊什么的,不是很好理解。于是我根据这篇文章的理解,用App进程、类来模拟进程间通信的过程,自己手写了一个进程间通信。
App进程:模拟安卓系统
MyBinder类:模拟Binder类
Process接口:表示进程
ProcessA:A进程
ProcessB:B进程
SystemServiceManager:模拟系统SystemService类
所有进程Process都是用单例模式,表示单个进程
1.先看进程类
public interface IProcess {
}
空接口,就表示一个进程
2.MyBinder?类
public class MyBinder {
//这个就是解决鸡生蛋蛋生鸡问题的那个预设的鸡
public static final String FIRST_BINDER = "0";
private static MyBinder sFirstBinder;
//进程名称
private String processName;
//进程的binder
private MyBinder processBinder;
//进程
private IProcess processProcxy;
private Parcelable data;
public MyBinder(String processName, MyBinder processBinder, IProcess processProcxy) {
this.processName = processName;
this.processBinder = processBinder;
this.processProcxy = processProcxy;
if (FIRST_BINDER.equals(processName)) {
if (null == sFirstBinder) {
sFirstBinder = this;
} else {
throw new RuntimeException("只能有一个初始化binder");
}
}
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
public MyBinder getProcessBinder() {
return processBinder;
}
public void setProcessBinder(MyBinder processBinder) {
this.processBinder = processBinder;
}
public IProcess getProcessProcxy() {
return processProcxy;
}
public void setProcessProcxy(IProcess processProcxy) {
this.processProcxy = processProcxy;
}
public static MyBinder getFristBinder() {
return sFirstBinder;
}
public Parcelable getData() {
return data;
}
public void setData(Parcelable data) {
this.data = data;
}
}
三个字段:
processName 进程名称,用于在systemservice中注册时用
processBinder 进程binder,用于在systemservice中注册时用
processProcxy 进程,记录当前进程的引用,可以通过binder拿到进程
还有一个sFirstBinder ,表示最原始的Binder,进程名字为0的进程,任意两个进程通信都先需要这个binder来开始
3.因为系统启动后,先创建的是SystemService进程,因此我们先看这个模拟类
public class SystemServiceManager implements IProcess {
//单例模式表示进程
private static volatile SystemServiceManager sSSMInstance;
//SystemService进程中的Binder实体,其实就是那个最原始的鸡Binder
private MyBinder mMyBinder;
//保存所有其他进程的Binder引用,key为进程名,value为binder引用
private HashMap<String, MyBinder> mAllBinder = new HashMap<>();
//构造器中创建SystemService进程的Binder实体,并且这个Binder名称为0,其他任何进程都可以获取到
private SystemServiceManager() {
mMyBinder = new MyBinder(MyBinder.FIRST_BINDER, null, this);
}
public static SystemServiceManager getInstance() {
if (null == sSSMInstance) {
synchronized (SystemServiceManager.class) {
if (null == sSSMInstance) {
sSSMInstance = new SystemServiceManager();
}
}
}
return sSSMInstance;
}
//其他进程通过这个方法将自己进程中的Binder引用在SystemService中注册
public void registProcessBinder() {
MyBinder processBinder = mMyBinder.getProcessBinder();
if (null != processBinder) {
mAllBinder.put(processBinder.getProcessName(), processBinder);
}
}
//通过进程名获取进程Binder引用的方法
public MyBinder getProcessBinder(String processName) {
return mAllBinder.get(processName);
}
}
4.ProcessA?进程A的代码
public class ProcessA implements IProcess {
//单例模式模拟进程A
private static volatile ProcessA sProcessA;
//进程A中的Binder实体
private MyBinder mMyBinder;
private ProcessA() {
//创建实体Binder
mMyBinder = new MyBinder(getClass().getSimpleName(), null, this);
//将Binder实体在SystemService中注册,注册过程是:通过Binder获取sFirstBinder---获取SystemService进程-----调用SystemService的注册方法(通过sFirstBinder将自己携带过去)
MyBinder.getFristBinder().setProcessBinder(mMyBinder);
((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).registProcessBinder();
}
public static ProcessA getInstance() {
if (null == sProcessA) {
synchronized (SystemServiceManager.class) {
if (null == sProcessA) {
sProcessA = new ProcessA();
}
}
}
return sProcessA;
}
private String name = "我是进程A";
public void getName(MyBinder binder) {
binder.setData(new Data(name));
}
public void setName(MyBinder binder) {
Data data = (Data) binder.getData();
name = data.getData();
Log.e("TAG", "setName: " + name);
}
/**
* 获取进程B的name字段
*/
public void getProcessBName() {
//获取进程B的name字段,通过Binder获取sFirstBinder---获取SystemService进程-----获取B进程的Binder----获取B进程引用----调用B进程的方法
MyBinder processBBinder = ((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).getProcessBinder(ProcessB.class.getSimpleName());
if (null != processBBinder) {
((ProcessB) processBBinder.getProcessProcxy()).getName(processBBinder);
Log.e("TAG", "getProcessBName: " + ((Data) processBBinder.getData()).getData());
}
}
/**
* 获取进程B的name字段
*/
public void setProcessBName() {
//获取进程B的name字段,通过Binder获取sFirstBinder---获取SystemService进程-----获取B进程的Binder----获取B进程引用----调用B进程的方法
MyBinder processBBinder = ((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).getProcessBinder(ProcessB.class.getSimpleName());
if (null != processBBinder) {
mMyBinder.setData(new Data("A进程给B进程设置的名字"));
((ProcessB) processBBinder.getProcessProcxy()).setName(mMyBinder);
}
}
}
5.同样的原理写B进程
public class ProcessB implements IProcess {
private static volatile ProcessB sProcessA;
private MyBinder mMyBinder;
private ProcessB() {
mMyBinder = new MyBinder(getClass().getSimpleName(), null, this);
MyBinder.getFristBinder().setProcessBinder(mMyBinder);
((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).registProcessBinder();
}
public static ProcessB getInstance() {
if (null == sProcessA) {
synchronized (SystemServiceManager.class) {
if (null == sProcessA) {
sProcessA = new ProcessB();
}
}
}
return sProcessA;
}
private String name = "我是进程B";
//获取数据,需要服务端,也就是自己的binder传递数据
public void getName(MyBinder binder) {
binder.setData(new Data(name));
}
//设置数据,需要客户端,也就是对方服务端的binder传递数据
public void setName(MyBinder binder) {
Data data = (Data) binder.getData();
name = data.getData();
Log.e("TAG", "setName: " + name);
}
/**
* 获取进程B的name字段
*/
public void getProcessAName() {
MyBinder processBBinder = ((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).getProcessBinder(ProcessA.class.getSimpleName());
if (null != processBBinder) {
((ProcessA) processBBinder.getProcessProcxy()).getName(processBBinder);
Log.e("TAG", "getProcessAName: " + ((Data) processBBinder.getData()).getData());
}
}
/**
* 获取进程B的name字段
*/
public void setProcessAName() {
MyBinder processBBinder = ((SystemServiceManager) MyBinder.getFristBinder().getProcessProcxy()).getProcessBinder(ProcessA.class.getSimpleName());
if (null != processBBinder) {
//模拟数据的一次拷贝过程
mMyBinder.setData(new Data("B进程给A进程设置的名字"));
((ProcessA) processBBinder.getProcessProcxy()).setName(mMyBinder);
}
}
}
6.最后我们看模拟系统代码
//模拟系统进程
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//启动SystemService进程
SystemServiceManager.getInstance();
//启动A进程
ProcessA.getInstance();
//启动B进程
ProcessB.getInstance();
//模拟A进程中获取B进程名字,这个方法应该在A进程中调用
ProcessA.getInstance().getProcessBName();
//模拟A进程中设置B进程名字,这个方法应该在A进程中调用
ProcessA.getInstance().setProcessBName();
//模拟B进程中获取A进程名字,这个方法应该在B进程中调用
ProcessB.getInstance().getProcessAName();
//模拟B进程中设置A进程名字,这个方法应该在B进程中调用
ProcessB.getInstance().setProcessAName();
}
}
这样我们就简单模拟了一下进程间通信。ProcessA和ProcessB之间不会有任何联系,都是通过系统服务类SystemServiceManager来实现的,而任意两个进程之间的交流,又都是通过Binder实现的,而且跨进程数据是一次拷贝。
补一个跨进程传递的数据类:
public class Data implements Parcelable {
private String data;
public Data(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.data);
}
public Data() {
}
protected Data(Parcel in) {
this.data = in.readString();
}
public static final Parcelable.Creator<Data> CREATOR = new Parcelable.Creator<Data>() {
@Override
public Data createFromParcel(Parcel source) {
return new Data(source);
}
@Override
public Data[] newArray(int size) {
return new Data[size];
}
};
}
demo?下载地址为:?demo
|