2015-09-11 3 views
2

Я реализую GCM в своем приложении для Android. Пока все хорошо, обмен сообщениями работает, но когда сообщение получено, приложение может или не может сбой с NullPointerException. Причина этого в том, что статическая ссылка иногда бывает null, а иногда нет, но причина, по которой это происходит, мне неизвестна.Статические объекты не всегда там, когда получено сообщение GCM

Объект, который может или не может быть нулевым является 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(...); 
обработка сообщений

ГКМ, как это:

@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

Потому что ваш процесс приложения убит, и вся память, которую он удерживал, была выпущена, пока вы ждали этого сообщения GCM. Когда ваше сообщение GCM было отправлено, система снова создает процесс приложения и объект Application, и вы получили нуль.

Просто проверьте, является ли экземпляр нулевым для вашего метода экземпляра get, и если его нуль воссоздает ваш объект.

EDIT: Невозможно убедиться, что один и тот же объект жив, система Android запускает сразу несколько приложений и не позволяет любому приложению заполнять память, поэтому она может убить ваш процесс, когда другим приложениям требуется память и это автоматически освободит вашу зарезервированную память, включая статические varaiables. Это ваша работа в качестве разработчика Android для решения этой проблемы :)

Чтобы избежать повторных и тяжелых вычислений при отдыхе, вам может потребоваться переосмыслить дизайн, чтобы состояние вашего объекта было постоянным, возможно, с помощью SharedPreferences.

+0

Есть ли способ сохранить ресурсы? В этом случае должна быть переделана целая цепочка аутентификации. – manabreak

+0

Кроме того, используйте GcmListenerService вместо того, чтобы делать свое собственное бодрствующее намерение. –

0

Сделайте свой MessageController переменным статическим.

+0

Это была опечатка с моей стороны. Вместо этого это будет комментарий. – manabreak

+0

Извините, stackoverflow еще не дал мне комментариев! :) –

0

Вы не можете гарантировать, что ваш объект статического контроллера будет жив (не равен). Поскольку приложение в фоновом режиме является идеальным кандидатом на GC.

Вы могли бы сохранить данные вашего GCM-сообщения в SQLite в том месте, где оно получено. И затем проверьте таблицу на данные при открытии приложения.

Смежные вопросы