本文主要讲解Android中的IPC机制
IPC简介
IPC是inter-Process-Communication的缩写,含义为进程间通信或者跨进程通信,是指两个进程之间交换数据的过程.说起进程间的通信,首先我们的理解什么是进程和线程,面试题必答题哈哈…当然了这两个肯定不是一回事.
线程: 按照操作系统中的描述.线程是CPU调度的最小单元,同事线程是系统的有限系统资源.
进程: 是指一个执行单元.在PC和移动端是指一个程序或者一个应用.
一个进程可以包含多个线程,因此进程和线程是包含于被包含的关系.最简单的情况下,一个进程只有一个线程,即主线程.在Android里边主线程也交错UI线程,在UI线程才能才能操作界面元素.很多时候一个进程中需要执行大量的耗时任务,如果这些任务放在主线程中执行,就会造成界面无法响应,严重影响用户体验,这种情况PC和移动端都会出现.在Android系统我们称之为ANR(Android Not Responding),即应用无响应.解决这个问题就需要用到线程,把一些耗时任务放在线程中即可.
Android中最有特色的进程间通信是Binder,Binder可以轻松实现进程间通信,除了Binder,Android还支持Socket,通过Socket也可以实现任意两个终端之间的通信,当然同一个设备两个进程通过Socket通信也是可以的.甚至我们使用系统提供的ContentProvider去查询数据的时候,也是一种进程间的通讯,只不过通信细节被系统屏蔽了.
IPC概念介绍
介绍一下IPC中的一些基础概念,主要包含三方面的内容:Serializable接口,Parcelable接口以及Binder,只有熟悉这三方面的内容后,我们才能更好理解进程间通信的各种方式.
Serializable接口和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent或Binder传输数据时就需要使用Parcelable或者Serializable.
Serializable接口
Serializable是java提供的序列化接口,他是一个空接口,为对象提供标准的序列化和反序列化的操作.
只要我们的自定义bean实现该接口就可以实现序列化操作(如下代码)
package cn.yuan.xiaoyu.testmodule.bean;
import java.io.Serializable;
/**
* Created by yukuoyuan on 2017/4/10.
*/
public class TestBean implements Serializable {
public int age;
public String name;
public String phone;
public String email;
@Override
public String toString() {
return "TestBean{" +
"age=" + age +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
", email='" + email + '\'' +
'}';
}
}
Parcelable接口
Parcelable 是一个接口,只要实现这个接口,一个类的对象就可以实现序列化并通过Intent 或者Binder传递(如下代码)
package cn.yuan.xiaoyu.testmodule.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by yukuoyuan on 2017/4/10.
*/
public class TestBean implements Parcelable {
public int age;
public String name;
public String phone;
public String email;
@Override
public String toString() {
return "TestBean{" +
"age=" + age +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
", email='" + email + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.age);
dest.writeString(this.name);
dest.writeString(this.phone);
dest.writeString(this.email);
}
public TestBean() {
}
protected TestBean(Parcel in) {
this.age = in.readInt();
this.name = in.readString();
this.phone = in.readString();
this.email = in.readString();
}
public static final Parcelable.Creator<TestBean> CREATOR = new Parcelable.Creator<TestBean>() {
@Override
public TestBean createFromParcel(Parcel source) {
return new TestBean(source);
}
@Override
public TestBean[] newArray(int size) {
return new TestBean[size];
}
};
}
方法说明
系统给我们提供了许多实现Parcelable接口的类他们都是可以直接序列化的.例如Intent,Bundle,Bitmap等,List和Map也可以序列化.前提是他们的元素类型是可以序列化的
Parcelable和Serializable区别
既然Parcelable和Serializable都能实现序列化并且都可用于Intent之间的数据传递,那么二者该如何选取呢?Serializable是Java中的序列化接口,其使用起来很简单但是开销很大.序列化和反序列化需要大量的IO操作.而Parcelable是Android中的序列化方式.因此更适合用在Android平台上.它的缺点是使用起来稍微复杂一点.但是它的效率很高.这是Android推荐的序列化方式.因此我们要首选Parcelable,Parcelable主要用于内存序列化上,通过Parcelable将对象序列化到存储设备或者将对象序列化后通过网络传输也都是可以的.但是这个过程会稍微复杂,因此在这两种情况下建议使用Serializable.以上就是Parcelable和Serializable的区别.
Binder
Binder 是一个很深入的话题
Binder是Android的一个类,它实现了IBinder接口,从IPC角度来说呢,BInder是Android中一种跨进程通信的方式.
在Android开发中,Binder主要用于Service中,包括AIDL和Messenger,其中普通Service中的Binder不涉及进程间的通信,所以较为简单,无法触及Binder的核心,其中Messenger的底层是AIDL,所以我们用AIDL来分析Binder的工作机制.
我们通过一个小demo来讲解
User.java
package cn.yuan.xiaoyu.testmodule.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by yukuoyuan on 2017/4/13.
*/
public class User implements Parcelable {
private int userId;
private String userName;
private int age;
private int sex;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.userId);
dest.writeString(this.userName);
dest.writeInt(this.age);
dest.writeInt(this.sex);
}
public User() {
}
protected User(Parcel in) {
this.userId = in.readInt();
this.userName = in.readString();
this.age = in.readInt();
this.sex = in.readInt();
}
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
//未完待续….