переменные поля области действия класса Activity будут доступны в AsyncTask, если родительский Activity закончен () - PullRequest
0 голосов
/ 09 сентября 2011

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

В моем Activity я запускаю AsyncTask.
Этот AsyncTask пишет в Sqlite, и онзаймет много времени.

Я думал, что смогу запустить AsyncTask, когда пользователь нажмет кнопку "Отправить"
, а затем нажмет кнопку "Назад", чтобы finish() Активность.

Я знаю, что AsyncTask будет продолжать работать, даже если Activity верно finish().

Вопрос в том, как сохранить поля живыми?

Что произойдет с localArrayPeople в этом коде, если родительский finish()?

private class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 
{
    ArrayList localArrayPeople;

    @Override
    protected Integer doInBackground(Long... params) {

        this.localArrayPeople =  arrayPeople;

        // Do stuff...
    }
}

Я знаю, что могу / должен использовать Сервис, но количество данных / Объектов для отправки в Service
действительно много.
Я знаю, что это плохой идеал, поэтому, пожалуйста, для образовательных целей просто ответьте на вопрос и не предупреждайте меня

Ответы [ 2 ]

2 голосов
/ 09 сентября 2011

Чтобы ответить на ваш вопрос.Объекты в Java-программах никогда не исчезают, поэтому поля не теряют ссылки, например, внезапно начинают указывать на ноль.Объекты удаляются GC только тогда, когда никто не ссылается на них.

В вашем случае, когда активность останавливается, поля в фоновом потоке не будут затронуты.

Единственная проблема может заключаться в том, что ОС Android принимает решениеудалить ваше приложение из памяти и убивает все его потоки.Это может произойти, если у вас действительно долго работает фоновый поток, а ваше приложение неактивно (= активность не отображается).

1 голос
/ 09 сентября 2011

Отвечая на исходный вопрос: +1 к @PeterKnego ответу.

Отвечая на ваш последний комментарий «Что мне делать, сделать localArrayPeople = null, когда я закончил?»: Нет, ваш AsyncTask содержит ссылку на Activity, поскольку каждый внутренний класс содержит ссылку на свой внешний класс (черезскрытое поле this$0).

Как указано в статье, на которую я ссылался в своем комментарии (« Предотвращение утечек памяти »):

Избегайтестатические внутренние классы в деятельности, если вы не управляете их жизненным циклом, используйте статический внутренний класс и даете слабую ссылку на деятельность внутри.

Таким образом, сделайте свой класс AsyncTaskDoStuff статическим inner one:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> 

Если вам нужно использовать объект Context в AsyncTask, передайте контекст приложения в конструктор AsyncTaskDoStuff:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final Context context;

   AsyncTaskDoStuff(Context context) {
     this.context = context;
   }

}

// in the activity:
AsyncTaskDoStuff async = new AsyncTaskDoStuff(getApplicationContext());

То же самое применимо, если вам нужночтобы прочитать некоторые поля Activity, передайте их через конструктор AsyncTaskDoStuff (или через его метод execute).

Если вам нужно изменить поля Activity в AsyncTask.doInBaМетод ckground делает следующее:

private static class AsyncTaskDoStuff extends AsyncTask<Long, Integer, Integer> {

   private final WeakReference<MyActivity> ref;

   AsyncTaskDoStuff(MyActivity activity) {
     this.ref = new WeakReference<MyActivity>(activity);
   }

   @Override
   protected Integer doInBackground(Long... params) {       
     MyActivity activity = ref.get();
     if (activity != null) {
       // access activity fields here
       activity.someField = ...
       ...
     } else {
       // activity object was already destroyed
     }
   }
}

// make sure accessed field is declared as volatile in the Activity
private volatile int someField;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...