Каков предпочтительный способ доступа к логике домена приложения из BroadcastReceiver в Android?

У меня есть приложение для Android, которое использует AlarmManager для планирования событий. При получении Намерения от AlarmManager логика домена должна выполнить некоторую работу, которая включает в себя доступ к БД и намерения вещания. В настоящее время я использую Singleton для доступа к доменной логике из BroadcastReceiver (зарегистрированного в манифесте) способом:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Singleton.getInstance().onAlarmFired();
    }
}

Этот Singleton используется в деятельности и услугах таким же образом. Он работает нормально, но Singleton считается анти-паттерном, и я хотел бы покрыть код тестами, поэтому я ищу другое решение.

Теперь вопрос в том, не лучше ли использовать Сервис вместо этого Синглтона? Как это:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        startService(new Intent(intent.getAction());
    }
}

Каковы преимущества и недостатки? И каким будет лучший способ общения с сервисом из Activity? Я думаю о привязке к сервису в MyApplication и предоставляю ссылку на действия и сервисы, используя метод getApplication().

1 ответ

Решение

Теперь вопрос в том, не лучше ли использовать Сервис вместо этого Синглтона?

Да, очень сильно. Основная директива, когда дело доходит до BroadcastReceiver.onReceive() Ответ тратить как можно меньше времени внутри метода, поскольку это выполняется в основном потоке, и если BroadcastReceiver жива более 10 секунд, быстро становится кандидатом на смерть ( подробнее см. в документации).

Вызов Service вместо этого выполнять работу является идеальной заменой реализации и возвращается из onReceive() очень быстро.

В зависимости от того, что ваш Service делает, вы можете привязать его к Activity вызывать методы или просто продолжать использовать Intents отправлять данные туда и обратно (возможно, вы захотите взглянуть на LocalBroadcastManager в библиотеке поддержки для последнего случая).

Я думаю о привязке к сервису в MyApplication и предоставляю ссылку на действия и сервисы, используя метод getApplication()

Я настоятельно призываю против этого. Я хотел бы рассмотреть возможность использования Application класс вообще во многих случаях тоже анти-паттерн. За его жизненным циклом следить не легче, чем за созданным синглтоном. Вместо этого, если вы хотите связать Service чтобы использовать его, свяжите его с любым Activity который хочет получить доступ, пока он находится на переднем плане.

РЕДАКТИРОВАТЬ: К вашему вопросу о системных службах

Системные сервисы и сервисы приложений очень разные; Системные сервисы вообще не являются сервисами (в определении слова SDK). Это объекты Singleton, которые работают внутри system_server процесс, где они защищены от сбоев, и поговорите с менеджерами объектов, к которым у вас есть доступ с использованием AIDL и IPC.

Синглтон в вашем приложении не имеет такой же роскоши. Если ваше приложение вылетает, Android не может помочь перезапустить ваш объект. Но что еще более важно, поскольку это не зарегистрированный системный компонент, Android не будет распознавать ваше приложение как выполняющее корректную фоновую работу, если вы выполняете код в фоновом режиме, и вы будете более вероятной целью для уничтожения памяти, если ваше приложение не на переднем плане.

Таким образом, хотя технически использование Singleton будет работать, перевод вашего кода в традиционный Service считается лучшей практикой и даст вам наибольшую выгоду от самой платформы.

Другие вопросы по тегам