收到GCM消息时,静态对象并不总是存在

时间:2015-09-11 12:23:06

标签: android google-cloud-messaging

我将GCM应用到我的Android应用中。到目前为止,消息传递很有效,但是当收到消息时,应用程序可能会或可能不会与NullPointerException一起崩溃。发生这种情况的原因是因为静态引用有时是null,有时不是,但我发现这种情况的原因并不为人所知。

可能为null的对象是MessageController,它是通过简单的服务定位器模式定位的,如下所示:

public class ControllerLocator
{
    private static MessageController controller; 

    public static MessageController getMessageController()
    {
        return controller;
    }

    public static void provide(MessageController mc)
    {
        controller = mc;
    }
}

控制器已在应用程序的onCreate()方法中设置:

@Override
public void onCreate()
{
    super.onCreate();
    ControllerLocator.provide(new MessageController());
}

// Later on in the program after backend authentication:
ControllerLocator.getMessageController().setCredentials(...);

GCM消息处理如下:

@Override
protected void onHandleIntent(Intent intent)
{
    Bundle extras = intent.getExtras();
    String msgType = GoogleCloudMessaging.getInstance(this).getMessageType(intent);
    if(msgType.equals(GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE))
    {
        handleMessage(extras.getString("message"));
    }

    GcmBroadcastReceiver.completeWakefulIntent(intent);
}

private void handleMessage(String msg)
{
    // 'controller' may or may not be null
    MessageController controller = ControllerLocator.getMessageController();
}

现在,实际情况:当应用程序在前台运行时,一切正常。但是,如果我按"返回"要退出关闭主活动并收到GCM消息,可能会或可能不会发生崩溃。

为什么静态引用会被删除?我如何解决这个问题以确保控制器始终存在?

3 个答案:

答案 0 :(得分:3)

这是因为您的应用程序进程被终止,并且在您等待该GCM消息时释放了它所拥有的所有内存。 当您的GCM消息传入时,系统会再次创建您的应用程序进程和Application对象,因此您将获得null。

只需检查get实例方法上的实例是否为null,如果null为null,则重新创建对象。

编辑: 没有办法确保同一个对象永远存在,Android系统一次运行许多应用程序并且不能允许任何应用程序填满内存,因此它可能会在其他应用程序需要内存时自动释放您的预留记忆包括静态变量。它是您作为Android开发人员处理它的工作:)

为了避免对娱乐进行重复计算和重度计算,您可能必须重新考虑您的设计,以便使用SharedPreferences来保持对象状态的持久性。

答案 1 :(得分:0)

MessageController变量设为静态。

答案 2 :(得分:0)

您无法确保静态Controller对象处于活动状态( not null ),因为后台的应用程序是GC的理想候选者。

然而,您可以在interval <- minutes(2) #Assuming this is how we define 5 minutes x$avg <- apply( x, 1, function(y){ mean(x$value[x$time > ( y["time"]) - interval ) && x$time < y["time"]]) }) 中将GCM消息数据保存在收到它的位置。然后在打开应用程序时查看表格中的数据。