一文带你了解Android IPC机制

带你了解Android IPC机制(上集)

1.IPC简介

首先,什么是IPC? 听起来好像有点高大上的感觉,其含义实际是进程间通信或跨进程通信,是指两个进程之间进行数据交换的过程。 如果这样说还不太理解,我们可以理解为,两个app之间的通信,首先两个app之间的通信肯定不能通过线程,所以提出IPC机制,解决多进程通信的问题。既然说的是进程间通信,我们必须要知道什么是进程,他和线程的区别是什么?

进程是资源分配的最小单位,线程是CPU调度的最小单位。进程有独立的内存地址,而线程没有。一个进程可以包含一个或多个线程。

IPC机制并不是Android独有的,我们常用的Windows操作系统linux操作系统中,复制粘贴也是IPC机制的一种实现。除此之外,Windows常用的方法还有管道邮槽来完成进程间通信。linux通过命名管道内存共享信号量等进行进程间的通信。对于Android来说,实现进程间通信的方法有Binder,Socket

2.如何开启多进程?

这个其实很简单,我们可以在配置清单中指定四大组件的一个属性

android:process=":romote"
android:process="com.ibuyi.free.remote"

这里我们讨论在一个app中的两个进程,对于多个app之间的进程其实原理也是相同的。

当我们的应用开启时,系统会用创建一个进程,进程名为完整的包名,如果我们使用
":remote"方式,省略完整包名,则系统会自动为我们添加上完整的包名。第二种就是直接指定完整包名的方法。这两种方式开启多线程略有不同。
区别:以“:”开头的,是当前应用的私有进程,而不是以“:”开头的是全局进程。

那么私有进程和全局进程又有什么区别呢?
如果进程是私有进程,则其他应用的组件不可以和它跑在同一个进程。如果是全局进程,可以通过shareUID方式和他跑在一个进程。如果这个不理解其实对下面的知识也没有影响。



3.多进程所带来的一些问题

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

对于第一点,如果是两个进程之间,Android为每一个进程分配一个独立的虚拟机,试想,都不在同一块内存中了,一个虚拟机中的静态成员变量发生变化,另一个虚拟机如何得知?
所以静态成员和单例模式都会失效。对于第二点,原因和第一点相同,如果不是位于同一个虚拟机中,线程同步机制就会失去作用。对于第三点,多进程模式下,SharedPreferences的稳定性会下降,我们知道sharedPreferences是基于XML的,它并不能在高并发的情况下保证稳定准确。对于第四点,运行在同一个进程中的组件是属于同一个虚拟机和同一个Application的,所以Application会被多次创建。

现在我们知道,多进程之间的通信会造成一些问题,那么如何避免?
我们先刷个副本,再去打最后这个怪
副本1.Serializable exp+100 hair–
副本2.Parcelable exp+100 hair–



4.Serializable

Android面试中经常会问道Serializable和parcelable的区别,我们先来了解一下Serializable
它是Java提供的一个序列化接口。
何谓序列化?
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程
何谓反序列化?
指把字节序列恢复为Java对象的过程

你可以这样理解一下序列化,比如说我们要把yUser的信息存储到硬盘,我们新建一个txt保存User中各个属性的值,当我们需要用的时候,再根据txt的值来恢复这个对象。但是有了序列化接口,我们就不必自己去写序列化对象的方法,可以直接用了

Serializable的使用方法很简单,我们只需要让我们的类实现Serializable接口,并在其中声明一个变量如下:

private static final long serialVersionUID=xxxxxxx

这个变量有什么作用呢?总不会是摆设吧?他的作用在于,当我们反序列化的时候需要判断,只有和当前类中的serialVersionUID相等我们才可以反序列化成功。为了防止别人对改序列化的文件做了修改,当我们反序列化的时候,如果不判断serialVersionUID,很有可能造成Crash。

我们写个demo来体会一下



public class User implements Serializable {
    public User(int userId,String userName,String passWord){
        this.userId=userId;
        this.userName=userName;
        this.passWord=passWord;
    }

    public static final long serialVersionUID=1111;
    public int userId;
    public String userName;
    public String passWord;


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化
        User user = new User(1, "no-hair", "no-money");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.txt"));
        out.writeObject(user);
        out.close();


        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.txt"));
        User rUser = (User) in.readObject();
        in.close();
    }
}


就是这么简单,我们就能把对象保存到本地,随时可以取出来转换成对象!有两点需要注意,第一静态变量不属于对象属于类,所以不会参与序列化过程,第二用transsient关键字修饰的变量不会参与序列化,大部分情况我们都不用重写里面的方法。

5.Parcelable

Parcelable是另一种序列化方式,和Serializable类似,他也是一个接口,一个类只要实现了这个接口,一个类的对象就可以实现序列化并通过Intent和Binder传递。下面还是通过一个简单的demo来看看parcelable.

public class User implements Parcelable {
    public User(int userId,String userName,String passWord){
        this.userId=userId;
        this.userName=userName;
        this.passWord=passWord;
    }

    public static final long serialVersionUID=1111;
    public int userId;
    public String userName;
    public String passWord;

//反序列化过程
    protected User(Parcel in) {
        userId = in.readInt();
        userName = in.readString();
        passWord = in.readString();
    }

    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[size];
        }
    };

    @Override
    public int describeContents() {
    //内容描述
        return 0;
    }
//序列化过程
    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(userId);
        parcel.writeString(userName);
        parcel.writeString(passWord);
    }
}

这个的使用方式和Serializable差不多简单,不多介绍,下面主要介绍两者的区别和特点。

6.Parcelable和Serializable的区别

既然两者都能够实现序列化和反序列化,那么我们该如何选择,这就要看使用场景了。
Serializable是Java中的序列化接口,使用简单但是开销很大,序列化和反序列化过程中需要大量的IO操作,而Parcelable是Android中序列化方式,他的缺点就是使用起来比较麻烦,但是他的效率高。在使用场景上,如果需要序列化到本地文件,数据库,网络流以方便传输,Android parcelable的设计初衷是由于Serializable的效率过低,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable 是通过 IBinder 通信的消息的载体。Parcelable 的性能比 Serializable 好,在内存开销方面较小,所以在内存间数据传输时推荐使用 Parcelable 。Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择 Serializable 。

猜你喜欢

转载自blog.csdn.net/weixin_43927892/article/details/105439818