34、IPC机制

一、IPC机制

1.1、Android IPC简介

IPC是Inter-Process Communication的缩写,含义为进程间通信或跨进程通信,是两个进程间进行数据交换的过程。

什么是线程?什么是进程?

线程是CPU调度的最小单元,同时线程是一种有限的系统资源。进程一般指一个执行单元,在PC和移动设备上指一个程序或应用。

  • 进程中包含了线程,所以他们是包含与被包含的关系。
  • 一个进程可以只有一个线程,就是主线程。

Android的进程通信并非完全继承自Linux,相反它有自己的通信机制,通过Binder完成跨进程通信,同时也支持socket通信。

1.2、多进程模式            

1、创建多进程的两种方式:
  • 在清单文件中给四大组件设置android:process属性。
  • 通过JNI在native层fork一个新的进程。
<activity android:name="cn.legend.remote.SecondActivity"
    android:process=":remote">
</activity>
<activity android:name="cn.legend.remote.ThirdActivity"
    android:process="cn.legend.remote">
</activity>

上面为两个Activity设置process属性,但是值却不一样,下面分析下区别:

  • :是简写方式,表示在前加上应用程序包名信息,它表示的是私有进程,其他组件无法运行在该进程中。
  • 全包名的是一种完整的命名方式,不会附加包名信息,它表示的是全局进程

Android系统会为每个应用分配UID,相同UID和签名相同的应用可以共享数据。

1.3、多进程模式的运行机制

我们在上面的示例中新建一个类UserManager,并在清单文件给SecondActivity配置process属性让其运行在一个独立进程中

public class UserManager {
    public static int mUserid = 1;
}

在MainActivity中我们给该静态变量赋值为2并打印

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    UserManager.mUserid = 2;
    Log.w("MainActivity:","mUserid = " + UserManager.mUserid);
}

当然我们在SecondActivity中也打印该变量

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
    Log.w("SecondActivity:","mUserid = " + UserManager.mUserid);
}

下面我们来看看运行后的结果:

15089660-3c78-4da3-a7be-aa2ca2ddc066

Android会为每个进程分配不同的虚拟机,它们在内存分配上有不同的地址空间,导致在不同虚拟机访问同一个对象会产生多个副本。

而我们的例子中,其实两个进程中相当于有两个UserManager类,它们互不影响,所以也就解释了上面的问题。

使用多进程造成的如下问题:

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

第一个问题和第二个问题本质上是相同的,都是不再同一块内存,而第三个问题是由于SharePreferences不支持两个进程同时读写,有几率丢失数据。

第四个问题是由于当有组件在新的进程中的时候,系统在创建新进程的同时分配独立的虚拟机,该过程其实是启动一个应用的过程。

二、IPC基础概念介绍

IPC机制主要包含三个方面:Serializable接口和Parcelable接口以及Binder。

Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要用Intent和Binder传输数据时需要它们。

1.1、Serializable

Serializable是Java所提供的一个序列化接口,是一个标记接口,为对象提供标准的序列化和反序列化操作。

public class User implements Serializable{
    private static final long serialVersionUID = 519067123721295773L;
    public int userid;
    public String userName;
    public boolean isMale;
    ...
}

实现Serializable接口后我们就可以对对象进行序列化和反序列化了,我们也可以不声明UID,但是这会给反序列化带来麻烦。

/**序列化过程*/
User user = new User(0, "jake", true);
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();

其中,UID是和成员变量计算有关的,如果不指定UID的话,如果成员变量发生改变,反序列化时就会报错。

1.2、Parcelable

Parcelable也是一个接口,只要实现该接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递。

待续

1.3、Binder

转载于:https://www.cnblogs.com/pengjingya/p/5510168.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值