IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 进程间通信之Binder理解之一 -> 正文阅读

[移动开发]进程间通信之Binder理解之一

这篇文章?我觉得写进程间通信,写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

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:22:54  更:2022-04-04 12:25:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 21:04:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码