Моя активность пытается создать AlertDialog, который требует Context в качестве параметра. Это работает, как ожидалось, если я использую:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Тем не менее, я опасаюсь использовать «this» в качестве контекста из-за потенциальной утечки памяти, когда Activity уничтожается и воссоздается даже во время чего-то простого, например, поворота экрана. Из соответствующего поста в блоге разработчика Android :
Есть два простых способа избежать утечек памяти, связанных с контекстом. Самый очевидный из них - избежать выхода за пределы контекста. В приведенном выше примере показан случай статической ссылки, но внутренние классы и их неявная ссылка на внешний класс могут быть одинаково опасными. Второе решение заключается в использовании контекста приложения. Этот контекст будет существовать до тех пор, пока ваше приложение живо и не зависит от жизненного цикла действий. Если вы планируете хранить долгоживущие объекты, которым нужен контекст, запомните объект приложения. Вы можете легко получить его, вызвав Context.getApplicationContext () или Activity.getApplication ().
Но для того , AlertDialog()
ни getApplicationContext()
или getApplication()
является приемлемым в качестве контекста, поскольку он бросает исключение:
«Невозможно добавить окно - токен ноль не для приложения»
Итак, действительно ли это следует считать «ошибкой», так как мы официально рекомендуем использовать, Activity.getApplication()
и все же он не функционирует так, как рекламируется?
Джим
Ответы:
Вместо того
getApplicationContext()
, чтобы просто использоватьActivityName.this
.источник
Listener
уроки часто анонимны, я просто стараюсь,final Context ctx = this;
и я ухожу;)Использование
this
не работает для меня, ноMyActivityName.this
сделал. Надеюсь, что это поможет любому, кто не смог добратьсяthis
до работы.источник
this
изнутри внутреннего класса. Если вы хотите сослаться на экземпляр внешнего класса, вы должны указать это, как вы делаете сOuterClass.this
. Просто использованиеthis
всегда ссылается на самый внутренний экземпляр класса.Вы можете продолжать использовать
getApplicationContext()
, но перед использованием вы должны добавить этот флаг:,dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
и ошибка не будет отображаться.Добавьте следующее разрешение в свой манифест:
источник
Вы правильно определили проблему, когда сказали «... для AlertDialog () ни getApplicationContext (), ни getApplication () не могут быть использованы в качестве контекста, так как они выдают исключение:« Невозможно добавить окно - токен null не предназначен для приложение'"
Чтобы создать диалог, вам нужен контекст действия или контекст службы , а не контекст приложения (оба метода getApplicationContext () и getApplication () возвращают контекст приложения).
Вот как вы получаете контекст действия :
(1) В действии или услуге:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) фрагментом:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Утечки памяти не являются проблемой, присущей ссылке «this», которая является ссылкой на объект самой себя (т. Е. Ссылкой на фактическую выделенную память для хранения данных объекта). Это происходит с любой выделенной памятью, для которой сборщик мусора (GC) не может освободиться после того, как выделенная память пережила свой полезный срок службы.
Большую часть времени, когда переменная выходит из области видимости, память восстанавливается GC. Однако утечки памяти могут возникать, когда ссылка на объект, содержащийся в переменной, скажем «x», сохраняется даже после того, как объект пережил свой полезный срок службы. Следовательно, выделенная память будет потеряна до тех пор, пока "x" содержит ссылку на нее, поскольку GC не освобождает память до тех пор, пока на эту память все еще ссылаются. Иногда утечки памяти не очевидны из-за цепочки ссылок на выделенную память. В таком случае GC не освободит память, пока не будут удалены все ссылки на эту память.
Чтобы предотвратить утечку памяти, проверьте свой код на наличие логических ошибок, которые приводят к тому, что на выделенную память бесконечно ссылаются «this» (или другие ссылки). Не забудьте также проверить ссылки на цепочки. Вот некоторые инструменты, которые вы можете использовать, чтобы помочь вам проанализировать использование памяти и обнаружить эти неприятные утечки памяти:
JRockit Mission Control
JProbe
YourKit
AD4J
источник
Ваш диалог не должен быть «долгоживущим объектом, которому нужен контекст». Документация сбивает с толку. В основном, если вы делаете что-то вроде:
(обратите внимание на статику )
Затем в деятельности где-то вы сделали
Скорее всего, во время ротации или чего-то подобного вы будете вытекать из исходного действия, что разрушит это действие. (Если вы не выполните очистку в onDestroy, но в этом случае вы, вероятно, не сделаете объект Dialog статическим)
Для некоторых структур данных имеет смысл сделать их статичными и основанными на контексте приложения, но, как правило, не для таких вещей, связанных с пользовательским интерфейсом, как диалоги. Так что-то вроде этого:
Это нормально и не должно пропускать активность, так как mDialog будет освобожден вместе с действием, поскольку он не является статичным.
источник
Мне пришлось отправить свой контекст через конструктор на настраиваемом адаптере, отображаемом во фрагменте, и у меня возникла эта проблема с getApplicationContext (). Я решил это с:
this.getActivity().getWindow().getContext()
в обратномonCreate
вызове фрагментов .источник
в Activity просто используйте:
во фрагменте:
источник
При
Activity
нажатии кнопки, показывающей диалоговое окноРаботал на меня.
источник
***** Котлин версия *****
Вы должны пройти
this@YourActivity
вместоapplicationContext
илиbaseContext
источник
Маленький хак: вы можете предотвратить уничтожение вашей деятельности с помощью ГХ (вы не должны делать это, но это может помочь в некоторых ситуациях Не забудьте установить.
contextForDialog
Чтобы ,null
когда он больше не нужен):источник
Если вы используете фрагмент и используете сообщение AlertDialog / Toast, тогда используйте getActivity () в параметре context.
нравится
источник
Просто используйте следующее:
ДЛЯ ПОЛЬЗОВАТЕЛЕЙ JAVA
Если вы используете активность ->
AlertDialog.Builder builder = new AlertDialog.Builder(this);
ИЛИ
AlertDialog.Builder builder = new AlertDialog.Builder(your_activity.this);
Если вы используете фрагмент ->
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
ДЛЯ КОТЛИН ПОЛЬЗОВАТЕЛЕЙ
Если вы используете активность ->
val builder = AlertDialog.Builder(this)
ИЛИ
val builder = AlertDialog.Builder(this@your_activity.this)
Если вы используете фрагмент ->
val builder = AlertDialog.Builder(activity!!)
источник
добавление
а также
"android.permission.SYSTEM_ALERT_WINDOW"/>
в манифестеЭто работает для меня сейчас. После даже закрытия и открытия приложения выдали ошибку на тот момент.
источник
Я использовал
ProgressDialog
во фрагменте и получал эту ошибку при передачеgetActivity().getApplicationContext()
в качестве параметра конструктора. Изменение егоgetActivity().getBaseContext()
не сработало.Решение, которое работало для меня, должно было пройти
getActivity()
; т.е.progressDialog = new ProgressDialog(getActivity());
источник
использование
MyDialog md = new MyDialog(MyActivity.this.getParent());
источник
Если вы находитесь за пределами действия, то вам нужно использовать в своей функции "NameOfMyActivity.this" в качестве действия активности, например:
источник
Если вы используете фрагмент и используете
AlertDialog / Toast
сообщение, используйтеgetActivity()
в параметре context.Работал на меня.
Ура!
источник
Попробуйте использовать контекст действия, которое будет под диалогом. Но будьте осторожны, когда используете ключевое слово "this", потому что оно не будет работать каждый раз.
Например, если у вас есть TabActivity в качестве хоста с двумя вкладками, и каждая вкладка является другим действием, и если вы попытаетесь создать диалог из одной из вкладок (действий) и если вы используете «this», то вы получите исключение, в этом диалог с делом должен быть связан с активностью хоста, на котором размещено все и что видно. (Вы можете сказать наиболее видимый контекст родительской активности)
Я не нашел эту информацию ни в одном документе, но пытаясь. Это мое решение без сильного фона, если кто-то с более известными знаниями, не стесняйтесь комментировать.
источник
Для будущих читателей это должно помочь:
источник
В моем случае работа:
источник
Или другой вариант - создать диалог следующим образом:
источник
Я думаю, что это также может произойти, если вы пытаетесь показать диалог из потока, который не является основным потоком пользовательского интерфейса.
Используйте
runOnUiThread()
в этом случае.источник
Попробуйте
getParent()
в контексте аргументации, например, newAlertDialog.Builder(getParent());
Надеюсь, это сработает, у меня сработало.источник
Взглянув на API, вы можете передать диалогу свою активность или getActivity, если вы находитесь во фрагменте, а затем принудительно очистить его с помощью dialog.dismiss () в методах возврата, чтобы предотвратить утечки.
Хотя это нигде не указано явно, мне кажется, что вам возвращают диалог в OnClickHandlers просто для этого.
источник
Если ваш диалог создается на адаптере:
Передайте упражнение конструктору адаптера:
Получите на адаптере:
Теперь вы можете использовать на вашем Builder
источник
Вот как я исправил ту же ошибку для своего приложения:
добавив следующую строку после создания диалога:
Вам не нужно приобретать контекст. Это особенно полезно, если вы открываете другой диалог поверх текущего всплывающего диалога. Или когда не удобно получать контекст.
Надеюсь, это поможет вам в разработке вашего приложения.
Дэвид
источник
источник