Передача контекста из сервиса в AsyncTask без утечки
У меня есть Service
из которой я AsyncTask
из заданного таймера для выполнения фоновых задач. Моя потребность требует коротких очередей сетевых задач, поэтому я и остаюсь с AsyncTask
.
Из AsyncTask
я выполняю ряд операций (таких как запуск уведомлений), которые требуют Context
. Теперь, когда я инициализирую Context
в моей AsyncTask
, я получаю предупреждение "Это поле AsyncTask
объект контекста".
Я видел несколько вопросов, касающихся одного и того же, но все они были связаны с Activity/Fragment
. Итак, мой вопрос, как я могу использовать Context
в моей AsyncTask
(класс верхнего уровня), не пропуская его?
Ответы
Ответ 1
У меня есть Служба, из которой я запускаю AsyncTask из заданного таймера для выполнения фоновых задач.
Не используйте AsyncTask
. Используйте поток. Или, еще лучше, использовал ScheduledExecutorService
для компонента синхронизации, поскольку это будет выполнять задачи в фоновом потоке. AsyncTask
подходит только тогда, когда вам нужно выполнять работу в основном потоке приложения, когда выполняется фоновая часть, и которая редко требуется для службы.
Кроме того, помните, что ваш таймер перестанет работать после завершения процесса.
Итак, мой вопрос: как я могу использовать контекст в моей AsyncTask (класс верхнего уровня) без его утечки?
Вызовите getApplicationContext()
на Service
и используйте Context
.
Ответ 2
Вы можете попробовать использовать WeakReference
и статический внутренний класс для вашего AsyncTask
для объекта, к которому вы пытаетесь получить доступ.
Что-то вроде этого:
class MyServiceWhichDoesNotLeak extends Service {
View view;
AsyncTask task;
//Your onCreate and stuff
private static class BackgroundTask extends AsyncTask<Void, Void, String> {
private final WeakReference<View> viewReference;
public BackgroundTask(View view) {
this.viewReference = new WeakReference<>(view);
}
@Override
protected String doInBackground(Void... params) {
// Background stuff
return "something";
}
@Override
protected void onPostExecute(String result) {
View view = viewReference.get();
if (view != null) {
//Use your view
}
}
}
}
Ответ 3
Вы можете передать WeakReference в AsyncTask, например:
public class MyAsynctask extends AsyncTask<Void, Void, Void> {
private WeakReference<Context> mWeakContext;
public MyAsynctask (WeakReference<Context> reference) {
mWeakContext = reference;
}
// when you need context use mWeakContext.get();
}
Надеюсь это поможет.