android线程间通信有哪些方式(android进程间通信方式讲解)

目录

进程间通信简介

Android中的多进程模式如何开启多进程多进程模式的运行机制

进程间通信基础概念介绍Serializable接口Parcelable接口
android线程间通信有哪些方式(android进程间通信方式讲解)

小结

进程间通信简介

进程间通信 即 IPC机制,IPC 全称为 Inter-Process Communication。

首先我们先了解下什么是进程,什么是线程?

进程:一般指一个执行单元。PC的一个程序 或者 移动设备的一个应用.

线程:CPU调用的最小单元,是一种有限的系统资源。

一个进程可以包含多个线程。

IPC 不是 Android 独有的,任何一个操作系统都需要相应的 IPC 机制。比如:

Windows上可以通过 剪切板、管道和邮槽来进行进程间通信。

Linux 上可以 命令管道、共享内存、信号量等来进行进程间通信。

Android 是一种基于 Linux内核 的移动操作系统,它的进程间通信并不能完全继承 Linux,它有自己的进程间通信方式,比如:Binder、Socket.

Android中的多进程模式

这里我们主要介绍两个问题:

如何开启开启多进程模式呢 ?

多进程的运行机制是怎样的呢 ?

如何开启开启多进程模式

那就是在 AndroidMainfest 文件中给 四大组件(Activity、Service、Receiver、ContentProvider) 指定 android:process。

当然 我们也可以通过 JNI 在 native层 去 fork 一个进程。

示例:

<activityandroid:name=”.SecondActivity”android:process=”:second”/><serviceandroid:name=”.TestService”android:process=”com.lxk.test.testService”/><receiverandroid:name=”.TestReceiver”android:process=”:testService”/><providerandroid:name=”.TestContentProvider”android:authorities=”lxk”android:process=”:testContentProvider”/>

:xxx 写法 会在前面添加当前的应用包名, 并且该进程为当前应用的私有进程。不用 :xxx 写法的 TestService 则属于全局进程,其他应用可以通过 shareUID 方式和它跑在一个进程中。

运行程序,我们可以通过以下 shell 命令来查看.com.lxk.test 为包名

adbshellps|grepcom.lxk.test多进程的运行机制

所以运行在不同进程中的四大组件,只要它们之间通过内存来共享数据,都会共享失败。

一般来说,使用多进程会出现以下问题:

静态成员和单例失效.

线程同步机制完全失效.

SharedPreferences的可靠性降低.

Application 会多次创建.

进程间通信基础概念介绍

这里我们是对 Serializable接口、Parcelable接口、Binder的介绍。

Serializable接口

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

使用示例:

publicclassUserimplementsSerializable{publicstaticfinallongserialVersionUID=4516876541857684L;publicintuserId;publicStringname;publicintage;}

我们只需要实现 Serializable 接口,其他的工作几乎都被系统自动完成了。

使用 ObjectOutputStream 和 ObjectInputStream 也可以轻松实现对象的序列化和反序列化。

Stringurl=”cache.txt”;Useruser=newUser(1,”lxk”,25);ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream(url));oos.writeObject(user);oos.close();ObjectInputStreamois=newObjectInputStream(newFileInputStream(url));UsernewUser=(User)ois.readObject();ois.close();

我们注意到示例中有个 serialVersionUID,它是用来做什么的呢?serialVersionUID 一般是 IDE 根据当前类的结构自动生成的它的 hash值,它并不是必须的。它的作用主要是用来 区分序列化的内容对应的类的结构是否发生了变化,如果结构发生了变化,就会导致序列化失败,程序crash.

当我们不需要序列化某些字段的时候,我们可以用 transient 字段来修饰.

publicclassUserimplementsSerializable{publicstaticfinallongserialVersionUID=4516876541857684L;publicintuserId;publicStringname;publicintage;publictransientinttemp;}Parcelable接口

Parcelable是 Android 提供的序列化方式。Parcelable 也是一个接口,我们只要实现这个接口,然后根据 AndroidStudio 的提示重写对应方法。

publicclassUserimplementsParcelable{publicstaticfinalCreator<User>CREATOR=newCreator<User>(){@OverridepublicUsercreateFromParcel(Parcelin){returnnewUser(in);}@OverridepublicUser[]newArray(intsize){returnnewUser[size];}};publicintuserId;publicStringname;publicintage;protectedUser(Parcelin){userId=in.readInt();name=in.readString();age=in.readInt();}@OverridepublicvoidwriteToParcel(Parceldest,intflags){dest.writeInt(userId);dest.writeString(name);dest.writeInt(age);}@OverridepublicintdescribeContents(){return0;}}

这里先说下,Parcel 内部包装了可序列化的数据,可以在 Binder 中自由传输。

通过以上示例代码,我们知道 序列化是由 writeToParcel 及 Parcel 的一系列 write 方法完成的,反序列化是由 CREATOR 及 Parcel 的一系列 read 方法完成的.

Parcelable的方法说明:

createFromParcel(Parcel in) :从序列化后的对象中创建原始对象.

newArray(int size) :创建指定长度的原始数据对象数组.

User(Parcel in) :从序列化后的对象中创建原始对象. | |

writeToParcel(Parcel dest, int flags) | 将当前对象写入序列化结构中. flags包含右侧标记为的值. PARCELABLE_WRITE_RETURN_VALUE = 0x0001 表示 正在写入的对象是一个返回值,一些实现可能在此时释放资源. PARCELABLE_ELIDE_DUPLICATES = 0x0002 表示父对象将负责管理名义上跨其内部数据成员复制的重复状态/数据. 几乎所有情况都是 0.

describeContents() :返回当前对象的内容描述. CONTENTS_FILE_DESCRIPTOR = 0x0001 表示包括文件描述符. 几乎所有情况都是 0.

系统为我们提供了许多实现了 Parcelable 接口的类,它们都是可以直接序列化的。比如:Intent、Bitmap、Bundle等,同时 List、Map也可以序列化。

Serializable 和 Parcelable对比Serializable 是Java提供的序列化接口,使用起来简单但是开销大,需要大量的 I/O操作。Parcelable 是 Android提供的序列化接口,适合在Android平台,缺点就是使用起来相对麻烦点,但是效率高。

内存序列化 选 Parcelable.序列化到存储设备 或者 序列化之后进行网络传输 则选 Serializable.

小结

介绍了通过在 AndroidMainfest 文件中给 四大组件指定 android:process 即可指定不同的进程。

介绍了 Serializable 和 Parcelable 接口的使用和优缺点,内存序列化 选 Parcelable,否则选 Serializable。

如果觉得不错的话,请帮忙点个赞呗。

以上

发表评论

登录后才能评论