andorxor 发表于 2018-7-24 15:01

Android 开发艺术探索读书笔记(三)

### 第 2 章 IPC 机制
本意主要讲解 Android 中的 IPC 机制。
#### 2.1 IPC 简介
IPC 是 Inter-Process Communication 的缩写,意为进程间通信,虽然 Android 是基于 Linux 内核的操作系统,但是它的进程通信方式并不完全继承自 Linux,在 Android 中,最有特色的进程间通信方式就是 Binder 了,通过 Binder 我们可以轻松地实现进程间的通信。
#### 2.2 Android 中的多进程模式
正常情况下,在 Android 中多进程是指一个应用中存在多个进程的情况,因此这里不讨论多个应用之间的多进程情况。

首先,在 Android 中使用多进程只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentPrivoder)在 AndroidManifest.xml 中指定 android:proces 属性。另外一种非常规的方法是通过 JNI 在 native 层 fork 一个新的进程,但这种方法属于特殊情况,这里暂时不讨论了。

下面来看一个多进程的示例:
```
<activity
    android:name=".SecondActivity"
    android:process=":remote" />
<activity
    android:name=".ThirdActivity"
    android:process="com.test.remote" />
```
这里使用了两种方式指定 android:process 的值,这两种方式是有区别的,通过“:”指定进程名是一种简单的写法,其完整名称应该为应用的包名加上 android:process 的名,在本例中为“com.test:remote”,而且这种写法表示进程属于当前应用的私有进程;ThirdActivity 中指定的进程名为完整的名称,对于不以“:”开头的进程来说,它们属于全局进程,其他应用可以通过 ShareUID 和它们跑在同一个进程中。

在 Android 中,系统会为第个应用分配一个唯一的 UID,只有具有相同 UID 且签名相同的应用才能共享数据,在这种情况下,两个应用可以互相访问对方的私有数据,如 data 目录、组件信息等。
同时,如果两个应用的 UID 和签名都相同,那么这两个应用就可以通过 ShareUID 跑在同一个进程中,这时两个应用不但可以共享私有数据,还可以共享内存数据,就像它们是同一个应用一样。

在 Android 中使用多进程会造成如下几个问题:
1. 静态成员和单例模式完全失效
2. 线程同步机制完全失效
3. SharedPreferences 的可靠性下降
4. Application 会多次创建

第 1 个问题是因为 Android 系统会为每个进程分配一个独立的虚拟机,这就导致了在多个进程中访问同一个类对象时会产生多个副本;第 2 个问题本质上和第 1 个问题是类似的;第 3 个问题是因为 SharedPreferences 不是线程安全的,所以并发读写 SharedPerferences 有可能会出问题;第 4 个问题还是因为系统要在创建新进程的同时分配一个独立的虚拟机,这个过程其实就是启动一个应用的过程,所以就会创建新的 Application。

针对多进程中存在的这些问题,Android 系统提供了很多跨进程通信的方法,比如通过 Intent、共享文件和 SharedPreferences 来传递数据,基于 Binder 和 Messager 和 AIDL 以及Socket 实现进程通信等。为了更好地理解 IPC 方式,我们先来熟悉一下 IPC 的基础概念。

#### 2.3 IPC 基础概念介绍
本节主要包含三个内容:Serializable 接口、Parcelable 接口和 Binder。

如果要使用 Serializable 来实现序列化,只需要让类实现该接口并在类的声明中指定如下字段即可:
```
private static final long serialVersionUID = 42L;
```
serialVersionUID 不是必须的,但如果序列化后的数据中有这个字段,那么只有这个 serialVersionUID 和当前类中的值相同才能正常地反序列化,下面是一个简单的序列化和反序列化的示例:
```
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    public int userId;
    public String userName;

    public User(int userId, String userName) {
      this.userId = userId;
      this.userName = userName;
    }
    ...

    private void test() throws Exception{
      // 序列化
      User user = new User(0, "jake");
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
      out.writeObject(user);
      out.close();

      // 反序列化
      ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
      User newUser = (User) in.readObject();
      in.close();
    }
}
```
Parcelable 也是一个接口,通过实现这个接口,我们可以让一个类的对象实现序列化并可以通过 Intent 和 Binder 传递,Parcelaable 和 Serializable 的区别在于,前者效率较高,但后者使用更简单,通常我们在内存序列化时使用 Parcelaable,如果要将对象持久化保存或者通过网络传输,则推荐使用 Serializable,下面是一个典型的用法:
```
public class User implements Parcelable {

    public int userId;
    public String userName;

    // 反序列化
    public static final Creator<User> CREATOR = new Creator<User>() {
      @Override
      public User createFromParcel(Parcel in) {
            return new User(in);
      }

      @Override
      public User[] newArray(int size) {
            return new User;
      }
    };

    public User(int userId, String userName) {
      this.userId = userId;
      this.userName = userName;
    }

    protected User(Parcel in) {
      userId = in.readInt();
      userName = in.readString();
    }

    // 仅当对象中存在文件描述符时才返回 1,其他情况下都返回 0
    @Override
    public int describeContents() {
      return 0;
    }

    // 序列化
    @Override
    public void writeToParcel(Parcel dest, int flags) {
      dest.writeInt(userId);
      dest.writeString(userName);
    }
}
```
最后再来说说 Binder,Binder 本身很复杂,它是 Android 中的一个类,且实现了 IBinder 接口。从 IPC 角度来说,Binder 是 Android 中的一种跨进程通信方式,也可以将 Binder 理解为一种虚拟的物理设备,它的设备驱动是 /dev/binder,该通信方式在 Linux 中是没有的;从 Android Framework 角度来说,Binder 是 ServiceManager 连接各种 Manager(ActivityMangager、WindowManager 等)和相应 ManagerService的桥梁;从 Androiid 应用层来说,Binder 是客户端和服务端进行通信的媒介,当 bindService() 的时候,服务端会返回一个包含了服务端业务调用的 Binder 对象,通过这个对象,客户端可以获取服务端提供的服务或数据,这里的服务包括普通服务和基于 AIDL 的服务。

上面一段是书中的介绍,感觉 Binder 确实很复杂,或者说 IPC 很复杂,这一章有点看不太懂了,暂时先跳过吧,以后慢慢学。。

抹杀你的浪漫 发表于 2018-7-24 19:23

大佬 带带我{:1_918:}
页: [1]
查看完整版本: Android 开发艺术探索读书笔记(三)