多进程导致 Application 多次执行的问题研究
2017-07-13 16:55
471 查看
在项目中我们有时会用到多进程,需要在 AndroidManifest 里进行声明 :
启动这个 Activity 后,你的应用就有了两个进程,这时就有问题了,Application 类的生命周期也调用了两次了:
至于为什么 Appilication 类的生命周期为什么会被调用两次,我们需要从底层进行分析,重点是看 Appilication 实例是在什么地方创建的,创建后生命周期是如何调用的;Activity 和 Application 都是普通的类,他们是在 ActivityThread 中创建的,并且给予了它们生命周期回调;
具体 Activity 启动流程可以看 Activity的启动流程
这里分析下与 Appilication 相关的内容
AMS 在收到发起者的 startActivity 请求后执行 ActivityStackSupervisor 的 startSpecificActivityLocked 方法
这里调用了 AMS 的 getProcessRecordLocked 方法来查是否在 AMS 中有相关的记录(应用的每个进程名字都会记录在 AMS 中),如果没有,返回的 app 为 null, 这时 调用的是 startProcessLocked 方法
在这里创建了一个新的进程,并且调用了 ActivityThread 的 main 方法,在 main 方法里创建了 ActivityThread 对象,也就是说每个进程对应了一个 ActivityThread 对象,然后 AMS 会通知 ActivityThread 的 handleLaunchActivity 来启动 Activity:
在这里调用 performLaunchActivity 创建了一个 Activity 和 Application
在这里先创建了 Activity 实例,再创建 Appilication 实例,并调用了 Activity 的 onCreate 方法,其中,在 makeApplication 里调用了 Application 的 onCreate 方法:
总结下,由于创建了新的进程,每个进程会创建自己的 ActivityThread 实例,每个 ActivityThread 又会创建自己的 Application 实例并且会调用它的 onCreate 方法;也就是说每个进程都会有自己的 Appilication 实例,而这个实例都用的同一个类来创建的,所以你在这个类里面写的东西当然会被执行多次;
所以这就是为什么同一个应用多进程会造成 Application 的生命周期方法会调用多次;
解决办法是在 Application 的生命周期方法里对进程名进行判断,如果不是同进程就不要执行一些不必要的东西了
<activity android:name=".RemoteActivity" android:process=":remote"/>
启动这个 Activity 后,你的应用就有了两个进程,这时就有问题了,Application 类的生命周期也调用了两次了:
07-13 10:03:40.069 22804 22804 D MyApplication: onCreate 07-13 10:03:40.885 22846 22846 D MyApplication: onCreate
至于为什么 Appilication 类的生命周期为什么会被调用两次,我们需要从底层进行分析,重点是看 Appilication 实例是在什么地方创建的,创建后生命周期是如何调用的;Activity 和 Application 都是普通的类,他们是在 ActivityThread 中创建的,并且给予了它们生命周期回调;
具体 Activity 启动流程可以看 Activity的启动流程
这里分析下与 Appilication 相关的内容
AMS 在收到发起者的 startActivity 请求后执行 ActivityStackSupervisor 的 startSpecificActivityLocked 方法
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { } } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
这里调用了 AMS 的 getProcessRecordLocked 方法来查是否在 AMS 中有相关的记录(应用的每个进程名字都会记录在 AMS 中),如果没有,返回的 app 为 null, 这时 调用的是 startProcessLocked 方法
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... if (entryPoint == null) entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); ... }
在这里创建了一个新的进程,并且调用了 ActivityThread 的 main 方法,在 main 方法里创建了 ActivityThread 对象,也就是说每个进程对应了一个 ActivityThread 对象,然后 AMS 会通知 ActivityThread 的 handleLaunchActivity 来启动 Activity:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ... Activity a = performLaunchActivity(r, customIntent); ... }
在这里调用 performLaunchActivity 创建了一个 Activity 和 Application
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... } catch (Exception e) { ... } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); ... if (activity != null) { ... if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } return activity; }
在这里先创建了 Activity 实例,再创建 Appilication 实例,并调用了 Activity 的 onCreate 方法,其中,在 makeApplication 里调用了 Application 的 onCreate 方法:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { ... app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); ... instrumentation.callApplicationOnCreate(app); return app; }
总结下,由于创建了新的进程,每个进程会创建自己的 ActivityThread 实例,每个 ActivityThread 又会创建自己的 Application 实例并且会调用它的 onCreate 方法;也就是说每个进程都会有自己的 Appilication 实例,而这个实例都用的同一个类来创建的,所以你在这个类里面写的东西当然会被执行多次;
所以这就是为什么同一个应用多进程会造成 Application 的生命周期方法会调用多次;
解决办法是在 Application 的生命周期方法里对进程名进行判断,如果不是同进程就不要执行一些不必要的东西了
相关文章推荐
- 多进程导致Application中onCreate执行多次
- 记一次诡异的问题:跟多进程多次执行application的onCreate有关
- DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
- [转载]DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
- Application中方法被执行多次??进程 -- 服务的坑 !!!
- 一个多线程问题引发的血案-(代码段执行完毕,子进程未执行完毕导致段错误)
- 多进程导致Application多次启动
- DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
- 多实例程序(Multiple Instance Application)中窗体调用 ShowDialog() 导致所有实例失去响应的问题, 及解决方案
- COM Interface Hooking and Its Application - Part I 示例程序执行中的问题
- Global.asax 不执行 Application_Start 问题
- 关于Oracle10.2.0自行启动两个监听进程导致服务中断问题
- VC:执行远程线程注入的代码段导致目标进程崩溃
- 构造函数的职责 -- 关于全局变量的构造函数里执行太多复杂操作导致的问题
- Android开发中Activity切换导致的onCreate重复执行的问题
- 配置win2003 server IIS的总结,为什么IIs的工作进程会在空闲时间释放的问题。同时学会了throw的真正含义,throw的真正含义就是导致程序停止,崩溃,很简单,网摘也有记录。
- 关于SIGPIPE导致进程终止的问题
- 警惕innerHTML赋值在IE下导致图片多次200的问题
- Oracle进程占用资源过大导致系统缓慢的问题
- 关于SVN导致电脑速度慢的问题,进程里TSVNCache.exe非常耗CPU