我是否正确使用AsyncTask?

时间:2018-12-02 12:44:39

标签: android android-asynctask

我正在读《专业Android》这本书,他们对AsyncTask说以下话:

  

请务必注意,异步任务对运行它们的组件的生命周期没有内在的了解。这意味着,如果要在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 :(得分:1)

您真的不应该那样睡在AsyncTask上。原因-所有AsyncTasks共享同一个线程(除非您调用executeOnExecutor)。这意味着如果一个任务正在运行,则系统中的其他AsyncTask都无法运行,直到完成。因此,AsyncTask应该非常快速且隔离。每次将要睡眠N次的时间不应该是异步任务。

对于这样的事情,正确的答案可能是将延迟的消息发布到Handler并在每次延迟时在UI线程上运行它。

对于实际上正在执行CPU密集型工作但需要像这样睡觉的事情,请使用线程。

答案 1 :(得分:0)

是的,您的异步任务正在捕获对Activity的{​​{1}}的强烈引用。也许是为了避免内存泄漏,您应该将TextView实例包装为TextView

有关此内容的更多信息:How to use WeakReference in Java and Android development?