Я получаю предупреждение в своем коде, в котором говорится:
Этот класс AsyncTask должен быть статическим, иначе могут возникнуть утечки (анонимный android.os.AsyncTask)
Полное предупреждение:
Этот класс AsyncTask должен быть статическим, иначе могут возникнуть утечки (анонимный android.os.AsyncTask). Статическое поле будет пропускать контексты. Нестатические внутренние классы имеют неявную ссылку на свой внешний класс. Если этот внешний класс является, например, Fragment или Activity, то эта ссылка означает, что долго выполняющийся обработчик / загрузчик / задача будет содержать ссылку на операцию, которая не позволяет собирать мусор. Точно так же прямые полевые ссылки на действия и фрагменты из этих более длительных экземпляров могут вызвать утечки. Классы ViewModel никогда не должны указывать на представления или контексты вне приложения.
Это мой код:
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
return null;
}
}.execute();
Как мне это исправить?
источник
myActivity.getApplication()
в закрытый конструктор для Singleton, чтобы инициализировать классы RoomDB и другие классы). Мои ViewModels получают экземпляр Singleton как частную ссылку для выполнения некоторых операций с БД. Итак, ViewModels импортирует пакет Singleton, а такжеandroid.app.Application
один из нихandroid.app.Activity
. Поскольку «Синглтону» не нужно импортировать эти ViewModel для работы, даже в этом случае могут возникнуть утечки памяти?Ответы:
Нестатические внутренние классы содержат ссылку на содержащий класс. Когда вы объявляете
AsyncTask
как внутренний класс, он может жить дольше, чем содержащийActivity
класс. Это из-за неявной ссылки на содержащий класс. Это предотвратит сбор мусора, что приведет к утечке памяти.Чтобы решить вашу проблему, используйте статический вложенный класс вместо анонимного, локального и внутреннего класса или класс верхнего уровня.
источник
Как использовать статический внутренний класс AsyncTask
Чтобы предотвратить утечки, вы можете сделать внутренний класс статическим. Однако проблема в том, что у вас больше нет доступа к представлениям пользовательского интерфейса Activity или переменным-членам. Вы можете передать ссылку на,
Context
но тогда вы рискуете утечкой памяти. (Android не может собирать мусор после закрытия, если класс AsyncTask имеет сильную ссылку на него.) Решение состоит в том, чтобы сделать слабую ссылку на действие (или все, чтоContext
вам нужно).Ноты
AsyncTask
учебники до сих пор с этим не справляются (см. Здесь , здесь , здесь и здесь ).AsyncTask
были классом высшего уровня. Статический внутренний класс в основном такой же, как класс верхнего уровня в Java.Если вам не нужна сама активность, но все же требуется контекст (например, для отображения a
Toast
), вы можете передать ссылку на контекст приложения. В этом случаеAsyncTask
конструктор будет выглядеть так:Котлин
В Kotlin просто не включайте
inner
ключевое слово для внутреннего класса. Это делает его статическим по умолчанию.источник
onPostExecute
метод еще раз в коде выше. Вы можете видеть, что я обновил пользовательский интерфейсTextView
там. Просто используйте,activity.findViewById
чтобы получить ссылку на любой элемент пользовательского интерфейса, который нужно обновить.activity.isFinishing()
чек и, возможно, заменили егоfragment.isRemoving()
чеком. Я не много работал с фрагментами в последнее время, хотя.AsyncTask
конструкторе вы передаете ссылку на ваш внешний класс. ИdoInBackground()
вы можете получить ссылку на внешний класс сMyOuterClass ref = classReference.get()
. Проверьте дляnull
. (2) УonPostExecute()
вас обновляется только пользовательский интерфейс с результатами фоновой задачи. Как и в любой другой раз, вы обновляете пользовательский интерфейс. Проверкаactivity.isFinishing()
состоит только в том, чтобы убедиться, что действие еще не начало завершаться, и в этом случае было бы бессмысленно обновлять пользовательский интерфейс.Этот
AsyncTask
класс должен быть статическим, иначе могут возникнуть утечкиActivity
уничтожен,AsyncTask
(обаstatic
илиnon-static
) все еще работаетnon-static
(AsyncTask
), он будет иметь ссылку на внешний класс (Activity
).Garbage Collected
будет освобожден. Если объект не используется иGarbage Collected
не может его освободить => утечка памяти=> Если
AsyncTask
естьnon-static
,Activity
не выпустит событие, оно уничтожено => утечкаРешение для обновления пользовательского интерфейса после создания AsyncTask как статический класс без утечки
1) Используйте
WeakReference
как @Suragch ответ2) Отправить и удалить
Activity
ссылку на (из)AsyncTask
источник
onDestroy()
не гарантируется, что он будет вызываться каждый раз