AsyncTask

原理

  • AsyncTask的特点是任务在主线程之外运行,而回调方法是在主线程中执行,AsyncTask其实使用handler来实现异步任务的,它是一个抽象类,AsyncTask的execute在主线程中首先调用了onPreExecute做预备工作,在子线程中调用了doInBackground方法去做耗时操作,返回的数据通过Message.obtain(handler, ON_POST_MSG, result).sendToTarget()发送在主线程里
  • handle的handleMessage方法调用了onPostExecute,更新ui
  • AsyncTask定义了三种泛型类型 Params,Progress和Result。 Params 启动任务执行的输入参数,比如HTTP请求的URL。 Progress 后台任务执行的百分比。 Result 后台执行任务最终返回的结果,比如String。 子类必须实现抽象方法doInBackground(Params… p) ,在此方法中实现任务的执行工作,比如连接网络获取数据等。通常还应 该实现onPostExecute(Result r)方法,因为应用程序关心的结果在此方法中返回。需要注意的是AsyncTask一定要在主线程中创 建实例。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    public abstract class MyAsynTask {
        protected static final int ON_POST_MSG = 0;
        private MyHandler handler;


        // 运行在主线程中,做准备工作
        protected abstract void onPreExecute();

        // 运行在子线程中,做耗时操作
        protected abstract String doInBackground(String s);

        // 运行在主线程中,耗时操作完成,更新ui
        protected abstract void onPostExecute(String s);

        public MyAsynTask() {
            handler = new MyHandler();
        }


        public void execute(final String... strs) {
            onPreExecute();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String result = doInBackground(strs[0]);
                    Message.obtain(handler, ON_POST_MSG, result).sendToTarget();
                }
            }).start();
        }


        class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case ON_POST_MSG:
                    String result = (String) msg.obj;
                    onPostExecute(result);
                    break;
                default:
                    break;
                }
                super.handleMessage(msg);
            }
        }
    }

MainActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void click(View v) {
        new MyAsynTask() {
            @Override
            protected void onPreExecute() {
                printLog("我在做准备操作");
                Toast.makeText(getApplication(), "我在做准备操作", 0).show();
            }


            @Override
            protected void onPostExecute(String s) {
                printLog("我接收到了结果:" + s);
                Toast.makeText(getApplication(), "我接收到了结果", 0).show();
            }


            @Override
            protected String doInBackground(String s) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                printLog("我在访问网络,参数是:" + s);
                return s + "返回";
            }
        }.execute(new String[] { "param1", "param2" });
    }

    public void printLog(String log) {
        System.out.println(Thread.currentThread().getName() + ":说:" + log);
    }

}

AsyncTask的优缺点

使用的优点:简单、快捷、过程可控      
使用的缺点:

  • AsyncTask的缺陷:可以分为两个部分说,在3.0以前,最大支持128个线程的并发,每次开启10个,5个同时运行,当开第129就会奔溃。在3.0以后,无论有多少任务,都会在其内部单线程执行。在执行多个异步操作时,一个运行其他的就得等待,需要自己开启线程池,比较麻烦,
  • 每次当一个任务执行完毕后,下一个任务才会得到执行,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。
  • 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.
  • AsynTask为什么要设计为只能够一次任务?最核心的还是线程安全问题,多个子线程同时运行,会产生状态不一致的问题。所以要务必保证只能够执行一次
    新版不对
1
2
3
4
5
6
7
8
9
10
11
private static final int CORE_POOL_SIZE = Math.max(2, 
Math.min(CPU_COUNT - 1, 4));//最大2

static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

Handler的优缺点
使用的优点:
结构清晰,功能定义明确
对于多个后台任务时,简单,清晰
使用的缺点:
在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)


AsyncTask
http://peiniwan.github.io/2024/04/c4144a02befd.html
作者
六月的雨
发布于
2024年4月6日
许可协议