Android中的IPC机制

IPC简介

IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。那么什么是进程,什么是线程,进程和线程是两个截然不同的概念。在操作系统中,线程是CPU调度的最小单元,同时线程是一种有限的系统资源。而进程指的一个执行单元,在PC和移动设备上指的是一个程序或者一个应用。一个进程可以包含多个线程,因此进程和线程是包含被包含的关系,最简单情况下,一个进程可以只有一个线程,即主线程,在Android里面也叫UI线程,在UI线程里才能操作界面元素。

那么在Android中,有特色的进程间通信方式就是Binder了,通过Binder可以轻松实现进程间通信。除了Binder,Android还支持Socket,通过Socket也可以实现任意两个终端之间的通信,当然一个设备上的两个进程之间通过Socket通信自然也是可以的。

说到IPC的使用场景就必须提到多进程,只有面对多进程这种场景下,才需要考虑进程间通信。所有运行在不同进程中的四大组件,只要它们之间需要通过内存来共享数据,都会共享失败,这也是多进程所带来的主要影响。正常情况下,四大组件中间不可能不通过一些中间层来共享数据,那么通过简单地指定进程名来开启多进程都会无法正确运行。一般来说,使用多进程会造成如下几方面的问题:

  • 静态成员和单例模式完全失效
  • 线程同步机制完全失效
  • SharedPreferences的可靠性下降
  • Application会多次创建

为了解决这个问题,系统提供了很多跨进程通信方法,虽然说不能直接地共享内存,但是通过跨进程通信我们还是可以实现数据交互。实现跨进程通信的方式有很多,比如通过Intent来传递数据,共享文件SharedPreference,基于Binder的Messenger和AIDL以及Socket等。

IPC基础概念介绍

Serializable接口
Serializable是Java提供的一个序列化接口,它是一个空接口,为对象标准的序列化和反序列化操作。使用Serializable来实现序列化相当简单,一句话即可。

public class User implements Serializable {
  private static final long seriaVersionUID = 519067123721295773L
}

Parcelable接口

Parcel内部包装了可序列化的数据,可以在Binder中自由传输,在序列化过程中需要实现的功能有序列化、反序列化和内容描述序列化功能有writeToParcel方法来完成,最终是通过Parcel中的一系列write方法来完成的。用法如下:

public class MyParcelable implements Parcelable {
    // You can include parcel data types
    private int mData;
    private String mName;
    
    // We can also include child Parcelable objects. Assume MySubParcel is such a Parcelable:
    private MySubParcelable mInfo;

    // This is where you write the values you want to save to the `Parcel`.  
    // The `Parcel` class has methods defined to help you save all of your values.  
    // Note that there are only methods defined for simple values, lists, and other Parcelable objects.  
    // You may need to make several classes Parcelable to send the data you want.
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
        out.writeString(mName);
        out.writeParcelable(mInfo, flags);
    }

    // Using the `in` variable, we can retrieve the values that 
    // we originally wrote into the `Parcel`.  This constructor is usually 
    // private so that only the `CREATOR` field can access.
    private MyParcelable(Parcel in) {
        mData = in.readInt();
        mName = in.readString();
        mInfo = in.readParcelable(MySubParcelable.class.getClassLoader());
    }

    public MyParcelable() {
        // Normal actions performed by class, since this is still a normal object!
    }

    // In the vast majority of cases you can simply return 0 for this.  
    // There are cases where you need to use the constant `CONTENTS_FILE_DESCRIPTOR`
    // But this is out of scope of this tutorial
    @Override
    public int describeContents() {
        return 0;
    }

    // After implementing the `Parcelable` interface, we need to create the 
    // `Parcelable.Creator CREATOR` constant for our class; 
    // Notice how it has our class specified as its type.  
    public static final Parcelable.Creator CREATOR
            = new Parcelable.Creator() {

        // This simply calls our new constructor (typically private) and 
        // passes along the unmarshalled `Parcel`, and then returns the new object!
        @Override
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        // We just need to copy this and change the type to match our class.
        @Override
        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };
}

Serializable和Parcelable区别
Serializable是Java中的序列化接口,其使用起来简单但是开销很大,在序列化和反序列化过程中需要大量的I/O操作。而Parcelable是Android中的序列化方式,因此更适合用在Android平台上,它的缺点就是使用起来稍微麻烦点,但是它的效率很高。

Binder
直观来说,Binder是Android中的一个类,它实现了IBinder接口。从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有。从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager等等)和相应ManagerService的桥梁。从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

Android中的IPC机制_第1张图片
Binder工作机制

Android中的IPC方式

使用Bundler
我们知道,四大组件中三大组件(activity、service、receiver)都是支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口,所以它可以方便地在不同的进程间传输。

使用文件共享
共享文件也是一种不错的进程间通信方式,两个进程间通过读/写同一个文件来交换数据,比如A进程把数据写入文件,B进程通过读取这个文件来获取数据。

使用Messenger
Messenger可以翻译为信使,顾名思义,通过它可以在不同进程中传递Message对象,在Message中放入我们需要传递的数据,就可以轻松地实现数据的进程间传递。Messenger是一种轻量级的IPC方案,它的底层实现是AIDL,实现Messenger有以下两个步骤,分为服务端进程和客户端进程。

Android中的IPC机制_第2张图片
Messenger工作原理

使用AIDL
远程服务跨进程通信的一种方式。

使用ContentProvider
ContentProvider是Android中提供的专门用于不同应用间进行数据共享的方式,它的底层实现同样也是Binder。

使用Socket
Socket也称为“套接字”,是网络通信中的概念,它分为流式套接字和用户数据套接字两种,分别应于网络的传输控制层中的TCP和UDP协议。

选用合适的IPC方式

Android中的IPC机制_第3张图片
不同IPC方式比较

你可能感兴趣的:(Android中的IPC机制)