0.  前言

不论是Android还是其他操作系统,都会有自己的IPC机制,所谓IPC(Inter-Process Communication)即进程间通信。首先线程和进程是很不同的概念,线程是CPU调用的最小单元,进程一般在PC和移动设备上指一个程序或者一个应用,一个进程可以包含多个线程。Android在一个应用中可以通过android:process属性开启多进程模式,用于某些模块必须运行在单独进程中或为一个应用多申请点内存。关于多进程的使用场景,详情可以参考Android开发——Android多进程以及使用场景介绍。该属性若以“:”开头则该进程属于当前应用的私有进程,否则属于全局进程。

虽然名为私有进程,但是可以为其再声明一个android:exported="true"属性,然后增加intent-filter属性(如果没有intent-filter属性,只能在本应用内使用),其他应用也可以关联到这个进程。

全局进程中假设有多个应用都声明了android:process="com.XX"全局进程的组件,会产生多个名字相同但PID并不相同的进程,所以全局进程并非全局唯一的意思。全局进程的作用是,其他应用可以通过ShareUID机制和这个全局进程跑在同一个进程中,从而共享资源。

IPC方式有很多,在Android中常用的IPC方式包括Bundle、文件、Messenger、AIDL、ContentProvider和Socket等方式。本篇主要讲解使用Bundle和文件的方式。本文原创,转载请注明出处为SEU_Calvin的博客。

1.  Bundle

Activity、Service、Receiver都是支持通过Intent传递Bundle数据的,由于Bundle实现了Parcelable接口,所以它可以方便的在不同的进程中传输。因此当我们在一个进程中启动了另外一个进程的Activity、Service、Receiver,我们就可以在Bundle中附加我们需要传输给远程进程的信息(前提是能够被序列化)并通过Intent发送出去。

下面是一个简单的示例,在一个应用中的MainActivity和BundleActivity(分属不同进程)之间使用Bundle传输数据。首先在MainActivity中使用Bundle包装我们的字符串数据。

Bundle bundle = new Bundle();
bundle.putString("ipc", "Bundle test");
Intent intent=new Intent(MainActivity.this,BundleActivity.class);
intent.putExtras(bundle);
startActivity(intent);

并在BundleActivity中进行数据接收,其中“ipc”作为某个Bundle数据单元的标识。

Bundle bundle=getIntent().getExtras();
//获取Bundle的信息
String info=bundle.getString("ipc");

2.  文件

2.1  思想

两个进程通过读写同一个文件来交换数据,利用这个思想,我们可以序列化一个对象到文件系统中,同时在另一个进程中反序列化恢复这个对象。

共享数据对文件格式没有具体要求,可以是文本文件,也可以是xml文件等等,主要注意处理并发读写的问题。

SharePreferences在底层实现上就是采用xml文件来存储键值对,但是SharePreferences的缓存策略使其在内存中会有一份缓存,因此在多进程模式下,系统对它的读写就变得不可靠。因此需要格外注意使用SharePreferences进行IPC。

2.2  transient

一个对象只要实现了Serilizable接口,这个对象就可以被序列化,但是一个类的有些属性需要序列化,而其他属性不需要被序列化(一个静态变量不管是否被transient修饰,均不能被序列化),就可以为这些变量加上transient关键字(不能修饰方法和类)。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

2.3  文件IPC示例

下面是一个简单的示例,首先定义一个User类,该类必须实现Serializable或者是Parcelable接口,这样便可以序列化。Serializable接口是Java提供的一个序列化接口,使用Serializable非常简单,只要直接User implements Serializable即可,当然也可以在User类中设置serialVersionUID,如下所示。

private static final long serialVersionUID = 519067123721295773L;  

这个serialVersionUID会随着序列化的行为被记录下来,若不设置serialVersionUID,当反序列化时该类若发生变化,如增加或删除了一些成员变量等等(修改类型等是不可以的),这样在校验serialVersionUID时没有找到类中的声明,系统会重新计算该值,那肯定就和以前记录的不一样啦,这样就会反序列化失败。

Parcelable接口在开销上较Serializable接口要小,更适合Android平台,Parcelable接口主要用于内存序列化上,当用于将对象持久化到存储设备或用于网络传输,使用Parcelable会很复杂,这种情况建议使用Serializable接口。

使用Parcelable接口的User类如下所示:

public class User implements Parcelable {  public int userId;  public String userName;  public User(int userId, String userName) {  this.userId = userId;  this.userName = userName;  }  public int describeContents() {  return 0;  }  public void writeToParcel(Parcel out, int flags) {  out.writeInt(userId);  out.writeString(userName);  }  public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {  public User createFromParcel(Parcel in) {  return new User(in);  }  public User[] newArray(int size) {  return new User[size];  }  };  private User(Parcel in) {  userId = in.readInt();  userName = in.readString();  }
}

剩下的就是在一个进程中将该对象序列化到文件中的操作:

User user = new User(1, "SEU_Calvin");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(mFilePath));
objectOutputStream.writeObject(user);

最后在另一个进程中从文件恢复之前存储的User对象的内容,之所以说是内容,是因为反序列化得到的对象只是在内容上和序列化之前的对象是一样的,但他们本质上是两个对象。

User user = null;
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(mFilePath));
user = (User) objectInputStream.readObject();

本篇介绍了Android中常见的IPC方式中的Bundle和文件,后面会陆续介绍其他的,如Messenger、AIDL、ContentProvider和Socket等方式。请大家多点赞支持~

Android开发——进程间通信之Bundle和文件相关推荐

  1. Android开发——进程间通信之AIDL(一)

    0.  前言 不论是Android还是其他操作系统,都会有自己的IPC机制,所谓IPC(Inter-Process Communication)即进程间通信.首先线程和进程是很不同的概念,线程是CPU ...

  2. Android开发中使用Bundle数据传值

    Bundle是Android开发中的一个类,用于Activity之间传输数据用,Bundle就是一个专门用于导入Intent传值的包. 1.MainActivity.xml 传输数据(4步) //设置 ...

  3. Android开发文件上传格式,(android开发)使用okhttp上传文件

    开发android手机客户端,常常会需要上传文件到服务器,比如:你手机里的照片. 使用okhttp会是一个很好的选择.它使用很简单,而且运行效率也很高. 首先,在 app/build.gradle 的 ...

  4. android开发 apk文件,android开发中,将数据库文件与APK一起发布?

    2015-11-11 回答 可以将xx.db文件复制到eclipse android工程中的res\raw目录中.所有在res\raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件. 使用op ...

  5. android rar文件怎么打开方式,android开发如何打开rar压缩文件

    释放双眼,带上耳机,听听看~! 有些文件是以压缩包的形式存在的,在打开之前需要对其进行解压,虽然大多数手机系统都有自己的解压功能,但当压缩包大于4GB时,使用自己的解压功能会导致文件损坏,那么andr ...

  6. android开发误删External Libraries下文件恢复问题

    吐血提示!! 手上项目为了兼容第三方解决冲突,删除了原有的aar包所有相关的,后要恢复,发现将aar放到libs包下,build里面也添加了 implementation(name: 'xx', ex ...

  7. Android开发关键知识点讲解

    有下载:http://download.csdn.net/detail/zl594389970/6281471 Android应用程序架构 src/  java原代码存放目录 gen/ 自动生成目录 ...

  8. 2020 Android 大厂面试-插件化、模块化、组件化,android开发环境的搭建视频

    if (Constants.COMBINE_RESOURCES) { //插件和主工程资源合并时需要hook住主工程的资源 Resources resources = ResourcesManager ...

  9. Android开发五 Android应用程序架构

    src/  java原代码存放目录gen/ 自动生成目录 gen 目录中存放所有由Android开发工具自动生成的文件.目录中最重要的就是R.java文件. 这个文件由Android开发工具自动产生的 ...

最新文章

  1. 能用条件注释改善的IE兼容问题
  2. laravel mysql json_mysql – Laravel JSON where子句不区分大小写
  3. 前端学习(2064):vue的生命周期函数有什么
  4. 奇怪的 Markdown / LaTeX 笔记
  5. VS2010 IDE安装问题
  6. Uncaught ReferenceError: jie is not defined
  7. gamit批量下载精密星历shell脚本
  8. Android 准确过滤(禁止) Emoji表情
  9. Maya动画2:刚体+重力模拟小球掉落
  10. python性能测试框架_python性能测试框架locust(一)
  11. 2021.10.07高一Python语法入门课堂检测题解
  12. 虚拟机无法通过dhcp获取到IP地址
  13. opencv4.5.2嵌入式移植
  14. marvin java_使用Java中的Marvin框架去除轮廓
  15. 有关球 圆柱 圆锥 的计算
  16. 【Shell】awk命令--输出某列,列求和,列求平均值,列最大值,列去重复,取倒列,过滤行,匹配,不匹配,内置变量|定义分隔符|多个分隔符...
  17. android 实现QQ好友列表
  18. Python案例-网络编程-socket入门-serverclient
  19. Win10休眠模式设置:开机后自动恢复工作界面,防止程序员虐待电脑
  20. 一个可以离线查询 IP 来源和 ISP 信息的终端利器

热门文章

  1. 好记性不如烂笔头——C++篇
  2. 面向DevSecOps的编码安全指南|JavaScript篇
  3. 扫地机器人充电插座布置_扫地机器人插座离地面多高合适 扫地机器人好不好用...
  4. QCAD与libreCAD的试用及比较,QCAD比libreCAD更好用,功能更强大
  5. Nuxt.js打包后报错DOMException: Failed to execute appendChild on Node
  6. numpy.linspace使用详解
  7. 计算两组2D bbox的IOU
  8. Windows 7恢复分区丢失了怎么恢复?
  9. 国际手机号码正则表达式
  10. hdu5544 Ba Gua Zhen(高斯消元)