(六)Android的IPC机制的基础

本文为Android的IPC相关知识整理,具体参考了

  • 《Android开发艺术探索》第二章 IPC机制

IPC,Inter-Process Communicatoin的缩写。即为Android进程间通信。


1,进程与线程

  • 线程是CPU调度的基本单位,进程一般指一个执行单元,在移动设备上指一个应用或者是一个程序。一个进程包含一个或多个线程。
  • 在Android中,一个程序可以只有一个线程,即主线程,也叫UI线程。在UI线程中才能操作界面元素,而不能在UI线程中执行大量耗时任务,否则会造成ANR,Application not responding错误。

Android线程(Thread)间通信:

  • Handle和Looper配合,消息队列机制。我们可以用AsyncTask类这个异步任务类。
  • 访问其他应用程序的Activity,通过Intent附带信息
    IntentcallIntent= newIntent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
    startActivity(callIntent);
  • ContentProvider,例如访问系统相册,通讯录,短信等
  • Broadcast 广播
  • AIDL,Android接口定义语言

Android进程(Process)间通信:

  • Binder
  • Socket
  • 文件共享
  • ContentProvider
  • Intent
  • Messenger

2,Android中的多进程

在Android中使用多进程只有一种方法,即给四大组件在AndroidManifest中指定android:process属性。

   <activity
         android:name="com.ryg.chapter_2.MainActivity"
         android:label="@string/app_name">
         <intent-filter>
             ....
         </intent-filter>
    </acitivty>
    <activity
         android:name="com.ryg.chapter_2.SecondAcitvity"
         android:process=":remote"/>
    <activity
         android:name="com.ryg.chapter_2.ThirdAcitvity"
         android:process="com.ryg.chapter.remote"/>

以上三个activity分别在以下进程中:

  • com.ryg.chapter_2,没有为组件指定process,那么这个组件就会运行在默认进程中。
  • com.ryg.chapter_2:remote,冒号的含义是在当前的进程名上附加当前的包名,此进程属于当前应用的私有进程。
  • com.ryg.chapter_2.remote,进程名不以冒号开头的进程属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中。

由于Android会为每一个进程提供单独的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,因而在不同的虚拟机中访问同一个类对象会产生多份副本。不同进程的虚拟机,Application,内存空间都不一样!!!!相当于两个不同的应用采用了SharedUID模式。

多进程引起的问题:

  • 静态成员和单例模式失效
  • 线程同步机制失效
  • SharedPreferences可靠性下降,其不支持两个进程同时执行写操作。
  • Application会多次重建

3,IPC基础概念

当我们需要通过Intent和Binder传输数据时,需要使用Serializable和Serializable接口来完成对象的序列化
当我们需要使对象持久化到存储设备上时,需要使用Serializable来完成对象的持久化

3.1 Serializable接口

这个是Java自带的,很简单但是内存开销大,只需要在类中加入serialVersionUID。适用于将对象序列化到存储设备或者将对象序列化后通过网络进行传输。

    public class User implements Serializable{
          private static final serialVersionUID = 4132904873290147032L;

          public int userId;
          public String userName;
          public boolean isMale;
    }

序列化和反序列化过程

     //序列化
    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();

恢复后的newUser对象和user内容完全一致,但不是同一对象。

为了避免反序列化失败,serialVersionUID 一般应该手动指定!!!其实也可以不指定serialVersionUID ,但这样的话是IDE自动根据类结构去生成hash值,这样的话我们对其的控制力就弱了,如果改变了类结构,就不能反序列化了!!!!而手动指定serialVersionUID 可以最大限度恢复数据。

3.2 Parcelable接口

这个是Android独有的,更适合用在Android平台,效率高,但是用起来有点麻烦。

    public class User implements parcelable{
          public int userId;
          public String userName;
          public boolean isMale;
          
          public User(int userId, String userName, boolean isMale){
              this.userId = userId;
              this.userName = userName;
              this.isMale = isMale;
          }

          public Book book;
          
          //内容描述
          public int describeContents(){
                return 0;
          }

          //序列化
          public void writeToParcel(Parcel out, int flags){
                out.writeInt(userId);
                out.writeString(userName);
                out.writeInt(isMale ? 1 : 0);
                out.writeParcelable(book, 0 );
          }

          //反序列化
          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();
                isMale = in.readInt() = 1;
                book = in.readParcelable(Thread.currentThread().getContextClassLoader());
          }
          
          
    }

3.3 Binder

  • 从IPC角度看,Binder是一种跨进程通信方式。
  • 从Android Freamwork角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager)和相应ManagerService的桥梁。
  • 从Android应用层将,Binder是客户端和服务器进行通信的媒介。

Android开发中,Binder主要用在Service中,包括AIDL,Messenger。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容