Android 由于多次调用应用程序onCreate(),在M上而不是在L上重新初始化静态变量

Android 由于多次调用应用程序onCreate(),在M上而不是在L上重新初始化静态变量,android,android-lifecycle,android-6.0-marshmallow,Android,Android Lifecycle,Android 6.0 Marshmallow,我有一个应用程序,它有一个从应用程序类派生的类,并且注意到它的onCreate()方法被多次调用。除此之外,每次调用onCreate()时都会重置其静态变量的值 这种行为只发生在M上,而不发生在L上。我试图找出它是M中的一个bug还是M中的一个预期变化,或者是应用程序架构中存在一些基本的固有问题,这些问题一直处于休眠状态,直到现在才在M中表现出来 每当调用广播接收器的onReceive()时,都会调用应用程序派生类的onCreate()。 未创建应用程序类的多个实例-正在对同一对象实例调用onC

我有一个应用程序,它有一个从应用程序类派生的类,并且注意到它的onCreate()方法被多次调用。除此之外,每次调用onCreate()时都会重置其静态变量的值

这种行为只发生在M上,而不发生在L上。我试图找出它是M中的一个bug还是M中的一个预期变化,或者是应用程序架构中存在一些基本的固有问题,这些问题一直处于休眠状态,直到现在才在M中表现出来

每当调用广播接收器的onReceive()时,都会调用应用程序派生类的onCreate()。 未创建应用程序类的多个实例-正在对同一对象实例调用onCreate(),并且始终存在相同的应用程序上下文

下面是一些代码片段,演示了这一观察结果:

public class MyApplication extends Application
{
    public static int debugVal = 5;

    public MyApplication ()
    {
        theApp = this;
    }

    public void onCreate ()
    {
        Log.v(TAG, "++++++++++++ onCreate() debugVal: " + debugVal);
        debugVal = 10;
        ....



public class MyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive (Context context, Intent intent)
    {
    Log.v(TAG, "onReceive. debugVal: " + MyApplication.debugVal);
    ...
在棉花糖上运行时,logcat输出为:

831-1412/? I/ActivityManager Start proc 2244:com.company.redacted/u0a86 for broadcast com.company.redacted/com.company.redacted2.MyBroadcastReceiver
2244-2244/? V/MyApplication: ++++++++++ onCreate() debugVal: 5
2244-2244/? V/MyBroadcastReceiver: onReceive. debugVal: 10
...
831-1327/? I/ActivityManager: Start proc 3271.com.company.redacted/u0a86 for broadcast com.company.redacted2/com.company.redacted1.MyBroadcastReceiver
3271-3271/? V/MyApplication: +++++++++++ onCreate() debugVal: 5
....
查看如何多次调用onCreate(),以及在第二次调用onCreate()时debugVal如何丢失其值10。 当相同的.apk在棒棒糖上运行时,对onCreate()的第二个调用不存在

L上的日志如下所示:

768-783/? I/ActivityManager: Start proc 2480:com.company.redacted/u0a84 for broadcast com/company.redacted1/com.company.redacted2/MyBroadcastReceiver
2480-2480/? V/MyApplication: +++++++++++ onCreate() debugVal:5
2480-2480/? V/MyBroadcastReceiver: onReceive. debugVal: 10
....
2480-2480/com.company.redaced1 v/MyBroadcastReceiver: onReceive. debugVal: 10
我想知道发生了什么并消除它,但是如果我不能,是否有可能用一些单例类替换应用程序类,这些单例类的静态变量被保证是安全可靠的,并且只初始化一次

这是一个预安装的应用程序,在启动时启动(这是接收器侦听的目的之一),此时没有任何活动。

您说在同一进程中调用onCreate()两次,但这可能是错误的。很可能棉花糖在杀死进程方面更具攻击性,要么是因为可用内存更少,要么就是在杀死空闲包方面更具攻击性(参见“empty#17”和其他名称)

要进行验证,请使用持久通知调用,使您的服务成为前台服务。如果您的问题消失,则意味着操作系统正在扼杀您的进程


一般来说,您不应该依赖于在后台运行—使初始化尽可能地懒惰和细粒度,并使后台操作(如广播接收器)尽可能便宜。

请注意,在您显示的日志消息中,整个过程会重新启动,因此再次调用onCreate,您能否描述两个事件之间发生了什么,或者您的应用程序正在做什么以及什么可以触发第一个进程的终止并启动一个新进程的一些细节?

静态变量不利于保持状态。这是因为静态变量无法在整个生命周期和应用程序启动/关闭期间存活。对于常量状态,通常只使用静态变量。这意味着变量具有相同的初始值或是常量

如果该值正在更改,则应将其存储在诸如Prefs之类的存储器中


至于为什么会有多个调用OnCreate;你能详细说明一下你正在实现什么样的广播接收机吗


传入的意图可能会导致配置更改,从而破坏并重新创建应用程序。

您对此有何评论?广播接收器日志是否显示在L上的不同进程中?我马上添加L中的日志。这是一个大型复杂的应用程序,需要一段时间才能将所有被注释掉的内容编成代码,可能太多太混乱而无法总结。super.onCreate()就在那里,只是不在我发布的简短代码片段中。不同的PID表明安卓肯定会两次启动两个单独的进程。要么第一次运行崩溃(检查logcat),要么您将服务配置为在一个隔离进程中运行(检查android:isolatedProcess的使用清单)。查看6.0源代码,我可以看到logcat输出行间接来自ActivityManagerService.java的第19088行,它决定终止一个空进程以释放一些内存。“空”流程是指静态数据已初始化,但不包含正在运行的应用程序组件(活动、服务等)的流程。我猜您的6.0平台比您的5.x平台更容易受到内存限制,您只是看到了操作系统在回收RAM方面更积极的影响。