几个基本概念
- Android为每一个应用分配一个独立的虚拟机,或者说每一个进程都分配一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,这就导致不同的虚拟机访问同一个类的对象会产生多分副本。
- Android对每个进程分配了虚拟机,早期的版本虚拟机堆内存只有16M
- 运行在同一个进程中的组件是属于同一个虚拟机和同一个Application的,也就是说有几个进程,我们在第一次启动的时候就要初始化几个Application,调用几次onCreate方法
为什么要考虑多进程模式实现一些内容?
- App有些功能模块特殊必须运行在单独的进程中。
- 为了加大一个应用可以使用的内存,需要多进程来获取多份内存空间。
- 当前应用需要向其它应用获取数据,两个应用必须使用跨进程方式获取数据。
开启多进程的方式
- 开启多进程的方法
- 对四大组件(Activity,Service,Receiver,ContentProvider)在AndroidMenifest中指定android:process属性
- 通过JNI在native层fork一个新的进程
本篇文章我们只讲解第一种开发多进程的方式
- 代码
<activity
android:name="com.koala.demo.MainActivity"
android:configChanges="orientation!screenSize"
android:label="@string/app_name"
android:launchMode="standard">
<intent-fliter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-fliter>
</activity>
<activity
android:name="com.koala.demo.SecondActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:process=":remote"/>
<activity
android:name="com.koala.demo.ThirdActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:process="com.koala.demo.remote"/>
查看进程信息
shell命令查看:adb shell ps 或者 adb shell ps | com.koala.demo ,其中com.koala.demo是包名
详细分析讲解
上面的代码,通过查看进程信息,我们开启了三个进程:
进入的时候MainActivity,com.kaola.demo创建
SecondActivity启动的时候com.kaola.demo:remote创建
ThirdActivity启动的时候com.kaola.demo.remote创建
:remote和.remote有什么区别呢?
:的含义当前进程名为签名附带上当前的包名,这是一种简写的方法。进程名以:开头的进程属于当前应用的私有进程,其他应用组件不可以和它跑在同一个进程中,而进程名不以:开头的进程属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中。
Android系统为每一个应用分配了一个唯一的UID,具有相同UID的应用才能共享数据。这里要说明的是两个应用通过ShareUID跑在同一个进程是有要求的,需要两个应用具有相同的ShareUID并且签名相同才可以,这种情况下,不管它们是否跑在同一个进程,它们可以互相访问私有数据,比如data目录,组件信息等
。如果跑在同一个进程中,除了共享data目录,组件信息,还可以共享内存数据,或者说它们看起来就像一个应用的两部分。
使用多进程会造成的问题
静态成员和单例模式完全失效
线程同步机制完全失效
既然不同的进程已经不是一块内存了,那么不管锁对象还是锁全局类都无法保证线程同步,因为不同进程锁不是同一对象
SharePreferences的可靠性下降
SharePreferences不支持两个进程同时去执行写操作,否则会导致一定几率的数据丢失,因为SharePrefeience底层是读/写xml文件来实现的,并发显然是可能有问题的
Application会多次创建(可以理解为开启一个进程就要创建一次Application)
参考:《Android开发艺术探索》