Вызывает диалоговое окно «Невозможно добавить окно - нулевой токен не для приложения» с getApplication () в качестве контекста - PullRequest
639 голосов
/ 27 апреля 2011

My Activity пытается создать AlertDialog, для которого в качестве параметра требуется Context. Это работает, как и ожидалось, если я использую:

AlertDialog.Builder builder = new AlertDialog.Builder(this);

Однако я опасаюсь использовать «это» в качестве контекста из-за потенциальной утечки памяти, когда активность разрушается и воссоздается даже во время чего-то простого, например, при повороте экрана. Из связанной записи в блоге разработчика Android :

Существует два простых способа избежать утечек памяти, связанных с контекстом. Самый очевидный из них - избежать выхода за пределы контекста. В приведенном выше примере показан случай статической ссылки, но внутренние классы и их неявная ссылка на внешний класс могут быть одинаково опасными. Второе решение заключается в использовании контекста приложения. Этот контекст будет существовать до тех пор, пока ваше приложение живо и не зависит от жизненного цикла действий. Если вы планируете хранить долгоживущие объекты, которым нужен контекст, запомните объект приложения. Вы можете легко получить его, вызвав Context.getApplicationContext () или Activity.getApplication ().

Но для AlertDialog() ни getApplicationContext(), ни getApplication() не могут быть использованы в качестве контекста, так как выдает исключение:

«Невозможно добавить окно - нулевой токен не для приложения»

по ссылкам: 1 , 2 , 3 и т. Д.

Итак, действительно ли это следует считать «ошибкой», поскольку нам официально рекомендуется использовать Activity.getApplication(), и, тем не менее, он не работает так, как рекламируется?

Jim

Ответы [ 23 ]

2 голосов
/ 05 февраля 2013

Попробуйте getParent() в контексте контекста аргумента, как новый AlertDialog.Builder(getParent()); Надеюсь, это сработает, у меня сработало.

2 голосов
/ 17 апреля 2013

Я думаю, что это также может произойти, если вы пытаетесь показать диалог из потока, который не является основным потоком пользовательского интерфейса.

Используйте runOnUiThread() в этом случае.

1 голос
/ 16 декабря 2014

Взглянув на API, вы можете передать диалогу свою активность или getActivity, если вы находитесь во фрагменте, а затем принудительно очистить его с помощью dialog.dismiss () в методах возврата, чтобы предотвратить утечки.

Хотя это нигде не указано явно, мне кажется, что вы вернулись обратно в диалог в OnClickHandlers просто для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...