美文网首页
Android IPC机制

Android IPC机制

作者: LeoFranz | 来源:发表于2019-09-26 17:14 被阅读0次

    跨进程有多种方式:

    • 基于Binder的AIDL、Messager、ContentProvider
    • 能够携带Bundle的intent
    • 跨进程文件共享
    • 基于socket的网络通信

    基于Binder的AIDL、Messager、ContentProvider

    Binder的原理
    我首先定义了Book.aidl、BookStoreInterface.aidl两个接口,先看下其结构:

    public interface BookStoreInterface extends android.os.IInterface{
    
    public static abstract class Stub extends android.os.Binder implements leo.com.bookstoredemo.BookStoreInterface
    {
    public Stub(){
    this.attachInterface(this, DESCRIPTOR);
    }
    public static leo.com.bookstoredemo.BookStoreInterface asInterface(android.os.IBinder obj)
    {
        if ((obj==null)) {
    return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof leo.com.bookstoredemo.BookStoreInterface))) {
    return ((leo.com.bookstoredemo.BookStoreInterface)iin);
    }
    return new leo.com.bookstoredemo.BookStoreInterface.Stub.Proxy(obj);
    }
    
    public android.os.IBinder asBinder()
    {
    return this;
    }
    private static class Proxy implements leo.com.bookstoredemo.BookStoreInterface
    {
    private android.os.IBinder mRemote;
    Proxy(android.os.IBinder remote)
    {
    mRemote = remote;
    }
    public android.os.IBinder asBinder()
    {
    return mRemote;
    }
    public java.util.List<leo.com.bookstoredemo.Book> getBooks()
    public void addBook(leo.com.bookstoredemo.Book book)
    }
    
    public java.util.List<leo.com.bookstoredemo.Book> getBooks() throws android.os.RemoteException;
    public void addBook(leo.com.bookstoredemo.Book book) throws android.os.RemoteException
    }
    

    再加上一张结构图就更加清楚


    image.png

    整体流程是这样的:
    客户端获取服务端的Stub.asInterface作为调用接口:

    • 客户端服务端在不同进程,该接口实现为Stub.proxy代理对象;
    • 客户端服务端在同一进程,该接口实现为Stub对象本身。
      服务端的Stub就是具体服务实现类。
      两端在不同进程的话,就通过Binder简建立持久连接。
      暴露的方法会被编码为int类型的静态常量,客户端和服务端就通过方法code形参确认调用的是哪个方法。
      proxy对象中的方法运行在客户端,当客户端调用某个function时候,代理中的_data获取方法参数(如果有),接着调用transact方法发起远程过程调用,同时当前线程挂起,服务端的OnTransact方法就会在服务端的Binder线程池中被调用,通过code确定目标方法,data获取方法参数,然后执行方法,完事后将结果存入reply中(如果有),如果该请求调用成功就返回true,否则就false,这个机制也可以用来做客户端权限验证。
      然后客户端收到服务端的返回数据,当前线程继续执行,并从reply中获取返回值(如果有)。

    这里注意服务端执行方法时候客户端线程是挂起状态,所以如果远端方法太耗时就不能在UI线程中发起远端请求。同时远端服务是一对多的状态,必须要处理好线程同步的问题。

    由上可知,当客户端和服务端在同一进程时候,方法调用不会走transact过程。

    image.png

    使用Messenger
    理解成跨进程的handler,底层通过AIDL实现,服务端传送Binder,客户端获取后能够利用该Binder生成Messenger
    https://www.jianshu.com/p/90330b9f0819

    使用AIDL
    https://www.jianshu.com/p/8c944d2284fd
    注意并发同步时候使用List用CopyOnWriteArrayList、hashMap使用ConcurrentHashMap

    ? 如何实现定时任务循环执行
    ?连接挂了怎么办
    ?Binder线程原理是什么

    ContentProvider
    底层实现也是binder,onCreate, query, update, delete, insert, getType, 运行在contentProvider所在进程,除了onCreate是系统调用运行在主线程,其他的方法均由外界调用并运行在Binder线程池中。
    外界对provider方法的调用会在不同线程中被执行,同时注意增删改查方法是支持多线程并发访问的,这点和AIDL服务端方法类似,需要手动控制好同步。
    加锁?
    如果被共享的数据是list和map使用CopyOnWriteList和ConcurrentHashMap就能实现自动同步
    如果只有一个SQLiteDatabase就能自动同步数据,因为其内部对数据库的操作有同步处理,但是如果有多个SQLiteDatebase链接就不能保证同步。

    能够携带Bundle的intent

    使用bundle携带实现了ParceLable|Serializable接口的对象或者基本程序对象。使用这些数据启动其他组件,传递消息。

    跨进程文件共享

    Socket

    有两种,流式套接字和用户数据包套接字,分别对应TCP和UDP,Socket本身支持传输任意字节流,注意不能在主线程中访问网络。当客户端连接时候就会生成一个新的socket,利用它可以和客户端通信
    socket还能实现不同设备之间的通信(双方IP地址可见)。

    ? Binder机制到底是什么

    相关文章

      网友评论

          本文标题:Android IPC机制

          本文链接:https://www.haomeiwen.com/subject/qqaoectx.html