Безопасно ли использовать ApplicationContext для диалога?

Я запускаю приложение, которое генерирует диалоговое предупреждение из Fragment в качестве сетевого обратного вызова. Для этого вам необходимо передать доступную ссылку Context; поскольку я использую Fragment s, я использую getActivity(). Из-за зависящего от сети характера обратного вызова getActivity() может иногда возвращать null. Это сбой моего кода.

Чтобы обойти эту ошибку, я надеялся предоставить ApplicationContext в диалоговом окне. Это синглтон, который сохраняется на протяжении жизни приложения, поэтому я знаю, что он не будет отозван. Кроме того, содержимое Dialog относится к подтверждению оплаты, поэтому я считаю, что разумные возможности для его отображения без строгой связи с определенным Window.

Это безопасная реализация? Я избегаю неизбежного и должен перейти к более устойчивой модели вообще?

Ответ 1

Это безопасная реализация?

ИМХО, нет.

Тактически, я ожидаю, что ваше приложение будет аварийно завершено в некоторых ситуациях (например, ваше приложение находится в фоновом режиме на момент завершения ввода-вывода в сети), и я ожидаю, что ваш диалог не обязательно будет соответствовать соответствующей теме. Поскольку, похоже, ваш "диалог" не привязан к активности, он должен быть активным в форме диалогового действия. Это решает проблему надежности и проблемы с вашей темой, хотя по-прежнему существует вероятность того, что вы отобразите диалоговое окно (-themed activity), когда пользователь находится в другом приложении, если ваш сетевой ввод-вывод занимает больше времени, чем вы ожидаете.

Стратегически, похоже, что вы заботитесь о результатах своих сетевых операций ввода-вывода независимо от того, что происходит на уровне пользовательского интерфейса вашего приложения. В этом случае ваш слой пользовательского интерфейса вашего приложения не должен быть непосредственно получающим результаты сетевого ввода-вывода, и кажется, что ваш фрагмент делает это прямо сейчас. Для управления сетевым вводом-выводом используйте что-то, что отключено от вашего пользовательского интерфейса (IntentService, JobService, голый поток, ThreadPoolExecutor). Используйте ли он шину событий (LocalBroadcastManager, greenrobot EventBus), чтобы сообщить уровню пользовательского интерфейса, что сетевой ввод-вывод завершен, и если слой пользовательского интерфейса не отвечает на событие (потому что он находится в фоновом режиме и вы только обратите внимание к событиям, когда пользовательский интерфейс виден), поднимите Notification или сделайте что-то еще тонкое, чтобы пользователь знал о результатах.

Ответ 2

Вам нужно использовать "Контекст действия" для вашего диалога, потому что Dialog является компонентом, который ожидает контекст пользовательского интерфейса. Поэтому перед отображением диалога вы можете проверить, добавлен ли текущий фрагмент в свою активность, используя метод isAdded():

if (isAdded()) {
    showDialog();
}