Я правильно использую AsyncTask? - PullRequest
0 голосов
/ 02 декабря 2018

Я читал книгу «Профессиональный Android», и они говорят следующее относительно AsyncTask:

Важно отметить, что у Async Tasks нет встроенного понимания жизненного циклакомпоненты, с которыми они работают.Это означает, что если вы создаете Async Task в Activity, чтобы избежать утечек памяти, вы должны определить его как статический (и убедиться, что он не содержит строгой ссылки на Activity или Views).

Для проверки Async Task я написал следующий код, который должен перевернуть строку в фоновом режиме и показать строящуюся строку постепенно, обновив TextView.Я использую сильную ссылку здесь?

package com.example.leo.test01;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private TextView textView;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.text_view_reversed_string);

        new reverseStringAsync(textView).execute("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    }

    private static class reverseStringAsync extends AsyncTask<String, String, String> {

        private TextView textView;

        reverseStringAsync(TextView textView) {
            this.textView = textView;
        }

        @Override
        protected void onPreExecute() {
            Log.d(TAG, "onPreExecute()");
            textView.setText("");
        }

        @Override
        protected String doInBackground(String... strings) {
            Log.d(TAG, "doInBackground()");
            int n = strings[0].length();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 1; i  <= n; i++) {
                stringBuilder.append(strings[0].charAt(n - i));
                publishProgress(stringBuilder.toString());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return stringBuilder.toString();
        }

        @Override
        protected void onProgressUpdate(String... values) {
            Log.d(TAG, "onProgressUpdate()");
            textView.setText(values[0]);
        }

        @Override
        protected void onPostExecute(String s) {
            Log.d(TAG, "onPostExecute()");
            textView.setText(s);
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Вы действительно не должны спать на AsyncTask, как это.Причина - все AsyncTasks совместно используют один и тот же поток (если только вы не вызываете executeOnExecutor).Это означает, что если выполняется одна задача, никакая другая AsyncTask в вашей системе не сможет работать до ее завершения.В результате AsyncTask должен быть очень быстрым и изолированным.То, что будет спать по N раз в секунду каждый раз, не должно быть асинхронной задачей.

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

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

0 голосов
/ 02 декабря 2018

Да, ваша асинхронная задача содержит строгую ссылку на Activity TextView.Возможно, чтобы избежать утечек памяти, вам следует обернуть экземпляр TextView WeakReference<TextView>.

Подробнее об этом здесь: Как использовать WeakReference в разработке на Java и Android?

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