android多进程深入分析
来源:互联网 发布:新手c#编程题及答案 编辑:程序博客网 时间:2024/05/16 19:51
android一个应用程序,可以存在多个进程, 在某些场景,比如希望获得更多的内存、希望功能模块间不相互影响,或者彻底解决webview内存泄漏等, 可以开多个进程;
看似好用且强大的多进程,也是一把双刃剑,今天就深入分析分析多进程;
前提明确一点: 进程间的内存空间是不可见的
测试项目源码地址
一、简要介绍android多进程的实现
在Manifest中,可以对Activity、Service、Broadcast receiver、Content Provider 四大组件,通过android:process属性设置独立进程,如下:
<activity android:name="com.tihi.multiprocess.SecActivity" android:process=":subprocesss" />打开的SecActivity界面,就运行在:subprocesss进程中了
二、下面进行多进程分析
1. 进程间全局静态变量共享吗?
测试验证:在主进程中修改全局静态变量, 在子进程中读取,查看值是修改后的还是修改前的;
如果值是修改后的,说明多进程共享全局静态变量,否则 说明不共享
(1)Manifest中, 声明两个界面,MainActivity 默认运行在主进程, SecActivity设置运行在独立进程 :subprocesss
<activity android:name="com.tihi.multiprocess.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.tihi.multiprocess.SecActivity" android:process=":subprocesss" />(2) 在常量类Consts.java中,定义一个全局静态变量
public class Consts { /** 静态全局变量 */ public static int num = 0;}
(3)在 MainActivity 中,把全局静态变量 num 设置为 100:
public class MainActivity extends FragmentActivity { private static final String TAG_PREFIX = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewUtils.inject(this); Util.printCurProThr(TAG_PREFIX); init(); } /** * 初始化 */ private void init() { Consts.num = 100; //在主进程,将全局变量值赋值为100 Logger.log(TAG_PREFIX + ", 全局静态变量值num为:" + Consts.num); }
private void testStatic(View view) { Logger.log(TAG_PREFIX + ", 全局静态变量值num为:" + Consts.num);}
结果如下: 子进程的SecActivity界面,打印出的全局变量num值为0,是未修改过的,说明 多进程间不共享全局静态变量, 切记哦,以免出现逻辑不正确;
推测:单例模式也不共享,因为内存不在一块
另外,从上图可以看出, MainActivity 运行的 进程名为com.tihi.multiprocess,即包名, SecActivity运行的进程名为 com.tihi.multiprocess:subprocesss
2. 多进程,Application实例创建一个还是多个?
测试验证:在 Application 类的 onCreate中,打印出当前的进程
public class App extends Application{ private static App _instance; private static final String TAG_PREFIX = "App"; @Override public void onCreate() { super.onCreate(); _instance = this; Util.printCurProThr(TAG_PREFIX + "_" + hashCode()); } public static App instance() { return _instance; }}
启动MainActivity,接着在界面上点击按钮,打开SecActivity,日志如下, 打开这两个界面时,分别创建了两个Application 实例, 如果需要针对不同进程区分对待的话,需要在代码中增加进程区分
3, 子进程启动主进程的界面,该界面在哪个进程运行?
测试验证: 有三个界面,MainActivity(主进程) 打开 --> SecActivity(子进程) 打开--> ThirdActivity(主进程)
日志如下,ThirdActivity界面虽然从子进程打开,但仍然运行在主进程
测试验证:有两个界面 MainActivity(主进程) --> SecActivity(子进程), 打开SecActivity界面时使用Intent传递参数
启动SecActivity代码: 传递了 personJson 字符串
public static void startAct(Context context, String personJson) { Intent intent = new Intent(context, SecActivity.class); intent.putExtra(INTENT_PENSON_KEY, personJson); context.startActivity(intent); }
日志如下: 说明跨进程 可以正确传递intent参数
5, 进程间,SharedPreference 内容共享吗?
测试验证:有两个界面 MainActivity(主进程) --> SecActivity(子进程), 主进程存储数据到share文件,子进程读取share,测试数据是否是主进程保存的
从日志看出, 子进程从share读取出的值与主进程存入的值是相同的,说明SharedPreference 进程间共享
推测:文件都是共享的,但可能存在进程并发的问题, 不同进程间的线程并发、锁就失效了
另外,进程间可以通过 广播等方式通信
6. 两个app应用(看做两个进程),通过BroadCast Receiver通信
测试验证:A应用发广播,B应用接收广播,并执行相应操作
A应用发送广播代码:
private void testAppBroad(View view) { Logger.log(TAG_PREFIX + ", Aapp, 发送广播啦"); Intent intent = new Intent(Consts.APP_BROAD_CAST_ACTION); intent.putExtra(Consts.APP_BROAD_CAST_INTENT_DATA_KEY, "appBroadTest"); sendBroadcast(intent); }
B应用接收广播代码:
private BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Util.printCurProThr("BApp, MainActivity"); if(intent != null) { String param = intent.getStringExtra(Consts.APP_BROAD_CAST_INTENT_DATA_KEY); Logger.log("BApp, 动态注册,接收到其他app发过来的广播,传递的值:" + param); } } };运行后,日志如下: BApp能正常接收广播内容, 广播接收者 的 onReceive运行在 UI主线程, 所以如果有耗时处理, 通过service启子线程去处理,广播声明周期只有10s, 避免ANR;
题外话: EventBus的消息通知,不能跨进程,如需跨进程通知,则请改用BroadCast Receiver;
网上说广播的生命周期只有10s, 但实测30s后都能继续执行,奇怪了
未完待续。。。
总结:
1, 进程间全局静态变量、单例模式 不共享,因为内存不在一块;
2,Application 类,每个进程会创建一个实例, 所以如果有多进程都需要使用的数据,不要放在Application 中;
3,线程的锁、对象锁机制,对多进程的线程无效;
4, 文件虽说是共享的,但多进程同时并发操作会有问题,sharedPreference不支持多进程同时写;
5,断点调试,Eclipse上开发android时,可以同时选择多个进程一起调试, 但Android studio一次只能选择一个进程调试;
- android多进程深入分析
- Android Binder进程间通信深入分析
- 进程的深入分析
- 深入理解Dalvik虚拟机- Android应用进程启动过程分析
- Android进程/线程管理——深入源码解读+分析
- linux深入分析进程调度
- Android AsyncTask深入分析
- Android Service深入分析
- android MediaPlayer深入分析
- android MediaPlayer深入分析
- Android Application 深入分析
- Android Gson深入分析
- Android:Service深入分析
- Android SystemProperties 深入分析
- Android ContentProvider深入分析
- android ProgressBar 深入分析
- Android动画深入分析
- Android动画深入分析
- rails 关于连接多个数据库使用同一个database.yml文件的方法
- 支付宝沙箱测试-ALI40247
- struts-default.xml和struts.properties
- linux(一)
- java注解
- android多进程深入分析
- VC 判断CString字符串中各位是数字,大小写字母,符号,汉字。(UNICODE和ANSI)
- Java程序员到架构师的推荐阅读书籍
- Python raw字符串(raw strings)
- POJ2559单调栈
- 笔记——数据结构入门
- Hadoop学习8_hadoop入门手册4:Hadoop【2.7.1】初级入门之命令:文件系统shell1
- 12Bet Malaysia Casino Weekly Bonus | Malaysia Online Casino (12bet,12bet malaysia casino,weekly bonu
- Git工具使用命令行总结