日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

教你寫Http框架(二)——三個例子帶你深入理解AsyncTask

 圖書館送餐人員 2016-03-16

這個標(biāo)題大家不要奇怪,扯Http框架怎么扯到AsyncTask去了,有兩個原因:首先是Http框架除了核心http理論外,其技術(shù)實現(xiàn)核心也是線程池 模板 handler,而AsyncTask又正好也是這三者的完美結(jié)合。其次,也是自己在面試中發(fā)現(xiàn)大量的安卓開發(fā)者完全不了解AsyncTask的原理和技術(shù)細(xì)節(jié),而AsyncTask的思想在我們設(shè)計app框架和性能調(diào)優(yōu)的時候是非常有用的。所以這里特地寫一篇關(guān)于AsyncTask的博文。
老規(guī)矩,我的習(xí)慣還是通過寫demo,把核心技術(shù)一點點剝離出來,一步步看完你就能深入理解其技術(shù)本質(zhì)了。

第一個例子,先理解Java的線程池和FutureTask。先說線程池,Java提供了一個非常重要的接口就是Executor。幾乎所有重要的線程池實現(xiàn)都繼承自這個接口,不過這個不是我們今天的重點,具體請查看Java的API手冊,我們上代碼看一下一般線程池是怎么實例化的。

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT   1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2   1;
private static final int KEEP_ALIVE = 1;

private static final BlockingQueue<Runnable> workQueue =
            new LinkedBlockingQueue<Runnable>(10);
private static final ThreadFactory threadFactory = new ThreadFactory()
{
    private final AtomicInteger count = new AtomicInteger(1);

    @Override
    public Thread newThread(Runnable r)
    {
        return new Thread(r, 'AsyncTask #'   count.getAndIncrement());
    }
};
private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR =
            new ThreadPoolExecutor(
                    CORE_POOL_SIZE, 
                    MAXIMUM_POOL_SIZE, 
                    KEEP_ALIVE, 
                    TimeUnit.SECONDS, 
                    workQueue, 
                    threadFactory);
  • 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

敏感的同學(xué)會發(fā)現(xiàn),這個就是AsyncTask的線程池的源碼,的確,正常的需求,這段代碼實例化出來的線程池基本都可以滿足了。其他參數(shù)看命名都很容易理解,這里主要講一下workQueue,因為我們會不斷提交任務(wù)給線程池執(zhí)行,而線程池的線程數(shù)量是有限的,當(dāng)所有核心線程都處于工作狀態(tài)時,client再次提交的任務(wù)放在哪里呢?我這么一問你就懂了吧。
再講一下java的FutureTask,我們知道正常情況下我們需要一個線程運行,提交的是一個Runnable,但有時候我們希望線程運行結(jié)束時帶回一個處理完成的數(shù)據(jù),這個時候Runnable就無力了,這個時候就要看FutureTask了。大家有興趣可以看一下它的源碼,其實它也是繼承自Runnable的,所以可以直接提交給線程來執(zhí)行。一般正常調(diào)用FutureTask的方法如下代碼:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Test1
{
    public static void main(String[] args)
    {
        Test1 test = new Test1();
        test.test();
    }

    public void test()
    {
        FutureTask<String> fTask = new FutureTask<String>(new Callable<String>()
        {
            @Override
            public String call() throws Exception
            {
                System.out.println('calling');
                return 'hello';
            }
        })
        {
            @Override
            protected void done()
            {
                try
                {
                    System.out.println('done '   get());
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                catch (ExecutionException e)
                {
                    e.printStackTrace();
                }

                super.done();
            }
        };

        Executor executor = Executors.newSingleThreadExecutor();
        executor.execute(fTask);
    }


}
  • 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
  • 49
  • 50
  • 51
  • 52

以上代碼的運行結(jié)果為:
calling
done hello
所以,我們在線程結(jié)束時拿到了最終的線程處理結(jié)果,而AsyncTask在onPostExecute中給你結(jié)果的時候,就是這么干的。

第二個例子,我們來點干貨,我們先寫個AsyncTask的例子,跑起來并看下運行結(jié)果,先代碼:

package com.amuro.activity;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.amuro.R;

public class MainActivity extends Activity
{

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

        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
               testAsync();
            }

        });
    }

    private void testAsync()
    {
        for(int i = 0; i < 10; i  )
        {
            final int j = i;
            AsyncTask<String, Integer, String> aTask =
                    new AsyncTask<String, Integer, String>()
            {
                @Override
                protected void onProgressUpdate(Integer... values)
                {
                    super.onProgressUpdate(values);
                }

                @Override
                protected String doInBackground(String... params)
                {
                    Log.e('amuro', Thread.currentThread().getName());
                    try
                    {
                        Thread.sleep(3000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    return params[0]   'done';
                }

                @Override
                protected void onPostExecute(String s)
                {
                    Log.e('amuro', 'result: '   s   ' '   j);
                }
            };
            aTask.execute('DoubleX');
        }
    }
}
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

看下運行結(jié)果:
03-13 11:23:47.950 22777-23081/com.amuro E/amuro: AsyncTask #1
03-13 11:23:50.955 22777-22777/com.amuro E/amuro: result: DoubleXdone 0
03-13 11:23:50.955 22777-23120/com.amuro E/amuro: AsyncTask #2
03-13 11:23:53.960 22777-22777/com.amuro E/amuro: result: DoubleXdone 1
03-13 11:23:53.960 22777-23195/com.amuro E/amuro: AsyncTask #3
03-13 11:23:56.965 22777-22777/com.amuro E/amuro: result: DoubleXdone 2
03-13 11:23:56.965 22777-23236/com.amuro E/amuro: AsyncTask #4
03-13 11:23:59.960 22777-22777/com.amuro E/amuro: result: DoubleXdone 3
03-13 11:23:59.965 22777-23277/com.amuro E/amuro: AsyncTask #5
03-13 11:24:02.965 22777-22777/com.amuro E/amuro: result: DoubleXdone 4
03-13 11:24:02.965 22777-23277/com.amuro E/amuro: AsyncTask #5
03-13 11:24:05.965 22777-22777/com.amuro E/amuro: result: DoubleXdone 5
03-13 11:24:05.970 22777-23277/com.amuro E/amuro: AsyncTask #5
03-13 11:24:08.975 22777-22777/com.amuro E/amuro: result: DoubleXdone 6
03-13 11:24:08.975 22777-23277/com.amuro E/amuro: AsyncTask #5
03-13 11:24:11.975 22777-22777/com.amuro E/amuro: result: DoubleXdone 7
03-13 11:24:11.975 22777-23277/com.amuro E/amuro: AsyncTask #5
03-13 11:24:14.980 22777-22777/com.amuro E/amuro: result: DoubleXdone 8
03-13 11:24:14.980 22777-23081/com.amuro E/amuro: AsyncTask #1
03-13 11:24:17.985 22777-22777/com.amuro E/amuro: result: DoubleXdone 9
可以看到,10個任務(wù)是順序執(zhí)行的,并且只有5個線程在工作,好,
我們把AsyncTask剛才那個線程池和FutureTask結(jié)合起來,寫一個簡單的例子實現(xiàn)和它一模一樣的功能。代碼:

package com.amuro;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Test2
{

    public static void main(String[] args)
    {
        Test2 test = new Test2();
        test.test();
    }

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT   1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2   1;
    private static final int KEEP_ALIVE = 1;

    private static final BlockingQueue<Runnable> workQueue =
            new LinkedBlockingQueue<Runnable>(10);
    private static final ThreadFactory threadFactory = new ThreadFactory()
    {
        private final AtomicInteger count = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r)
        {
            return new Thread(r, 'AsyncTask #'   count.getAndIncrement());
        }
    };
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR =
            new ThreadPoolExecutor(
                    CORE_POOL_SIZE, 
                    MAXIMUM_POOL_SIZE, 
                    KEEP_ALIVE, 
                    TimeUnit.SECONDS, 
                    workQueue, 
                    threadFactory);

    private static volatile Executor defaultExecutor = new Executor()
    {
        final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>();
        Runnable activeRunnable;

        @Override
        public void execute(final Runnable r)
        {
            tasks.offer(new Runnable()
            {

                @Override
                public void run()
                {
                    try
                    {
                        System.out.println(Thread.currentThread().getName());
                        r.run();
                    }
                    finally
                    {
                        scheduleNext();
                    }
                }
            });

            if(activeRunnable == null)
            {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext()
        {
            if((activeRunnable = tasks.poll()) != null)
            {
                THREAD_POOL_EXECUTOR.execute(activeRunnable);
            }
        }
    };

    public void test()
    {
        List<FutureTask<String>> fList = new ArrayList<FutureTask<String>>();
        for(int i = 0; i < 10; i  )
        {
            final int j = i;

            fList.add(new FutureTask<String>(new Callable<String>()
            {

                @Override
                public String call() throws Exception
                {
                    Thread.sleep(3000);
                    return 'I'm callable '   j;
                }
            }){
                @Override
                protected void done()
                {
                    try
                    {
                        System.out.println(get()   ' done');
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    catch (ExecutionException e)
                    {
                        e.printStackTrace();
                    }
                }
            }

            );
        }

        for(FutureTask<String> fTask : fList)
        {
            defaultExecutor.execute(fTask);
        }
    }

}
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137

先看運行結(jié)果:
AsyncTask #1
I’m callable 0 done
AsyncTask #2
I’m callable 1 done
AsyncTask #3
I’m callable 2 done
AsyncTask #4
I’m callable 3 done
AsyncTask #5
I’m callable 4 done
AsyncTask #5
I’m callable 5 done
AsyncTask #5
I’m callable 6 done
AsyncTask #5
I’m callable 7 done
AsyncTask #5
I’m callable 8 done
AsyncTask #5
I’m callable 9 done
是不是一模一樣~沒錯其實我們正常調(diào)用AsyncTask的execute方法的時候,就是調(diào)用了這個defaultExecutor,它的作用就是維持了一個雙向的任務(wù)隊列,當(dāng)AsyncTask的execute方法執(zhí)行的時候,它就把client提交的任務(wù)塞到了這個隊列里,如果這時候沒有任務(wù)在執(zhí)行,activeRunnable就為null,則scheduleNext方法直接調(diào)用,這個剛被提交的任務(wù)就會從隊列中被取出交給線程池區(qū)執(zhí)行,執(zhí)行完成后又會繼續(xù)調(diào)用scheduleNext方法,有任務(wù)就會繼續(xù)執(zhí)行下一個任務(wù)。所以你看到的結(jié)果就是這樣一個順序執(zhí)行,并且線程池只使用了5個線程,充分利用了資源。補充一點,AsyncTask的源碼中,如果你想把所有任務(wù)改為并行執(zhí)行,是可以傳一個自己的Executor進(jìn)來的,但是這個方法被hide了,看來是官方不建議大家這么做。

理解了上面兩個例子的話,第三個例子寫起來就so easy了,沒錯,理解輪子的最好試金石就是自己寫個輪子,所以下面我們就是要簡單地寫一個自己的AsyncTask,和java直接run最大的區(qū)別就是安卓的非UI線程不能操作UI線程的實例,這個時候,把handler君請過來就好了嘛~ 還是先看代碼,我們自定義一個MyAsyncTask:

package com.amuro.thread;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;

import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.LogRecord;

/**
 * Created by Echo on 2016/3/12.
 */
public abstract class MyAsyncTask<Params, Result>
{
    /*************線程池核心代碼*******************/
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT   1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2   1;
    private static final int KEEP_ALIVE = 1;

    private static final BlockingQueue<Runnable> workQueue =
            new LinkedBlockingQueue<Runnable>(10);
    private static final ThreadFactory threadFactory = new ThreadFactory()
    {
        private final AtomicInteger count = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r)
        {
            return new Thread(r, 'MyAsyncTask #'   count.getAndIncrement());
        }
    };
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR =
            new ThreadPoolExecutor(
                    CORE_POOL_SIZE,
                    MAXIMUM_POOL_SIZE,
                    KEEP_ALIVE,
                    TimeUnit.SECONDS,
                    workQueue,
                    threadFactory);

    private static volatile Executor defaultExecutor = new Executor()
    {
        final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>();
        Runnable activeRunnable;

        @Override
        public void execute(final Runnable r)
        {
            tasks.offer(new Runnable()
            {

                @Override
                public void run()
                {
                    try
                    {
                        r.run();
                    }
                    finally
                    {
                        scheduleNext();
                    }
                }
            });

            if(activeRunnable == null)
            {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext()
        {
            if((activeRunnable = tasks.poll()) != null)
            {
                THREAD_POOL_EXECUTOR.execute(activeRunnable);
            }
        }
    };

    /****************消息處理核心代碼************************/
    private static final int MESSAGE_POST_RESULT = 0x01;

    private static class AsyncTaskResult<Data>
    {
        final MyAsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(MyAsyncTask task, Data... data)
        {
            mTask = task;
            mData = data;
        }
    }

    private static abstract class WorkerRunnable<Params, Result>
            implements Callable<Result> {
        Params[] mParams;
    }

    private static final Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what)
            {
                case MESSAGE_POST_RESULT:
                    result.mTask.finish(result.mData[0]);
                    break;
            }
        }
    };
    private final WorkerRunnable<Params, Result> workerRunnable;
    private final FutureTask<Result> futureTask;

    public MyAsyncTask()
    {
        workerRunnable = new WorkerRunnable<Params, Result>()
        {
            @Override
            public Result call() throws Exception
            {
                return postResult(doInBackground(mParams));
            }
        };

        futureTask = new FutureTask<Result>(workerRunnable);
    }

    private Result postResult(Result result)
    {
        Message message = handler.obtainMessage(
                MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

    private void finish(Result result)
    {
        onPostExecute(result);
    }

    protected void onPreExecute(){}

    protected abstract Result doInBackground(Params... params);

    protected void onPostExecute(Result result){}

    public final MyAsyncTask<Params, Result> execute(Params... params)
    {
        return executeOnExecutor(defaultExecutor, params);
    }

    public final MyAsyncTask<Params, Result> executeOnExecutor(Executor executor, Params... params)
    {
        onPreExecute();

        workerRunnable.mParams = params;
        executor.execute(futureTask);
        return this;
    }
}
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176

然后再看一下調(diào)用的代碼:

package com.amuro.activity;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.amuro.R;
import com.amuro.thread.MyAsyncTask;

public class MainActivity extends Activity
{

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

        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
               testAsync();
            }

        });

        findViewById(R.id.bt1).setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                testMyAsync();
            }
        });
    }

    private void testAsync()
    {
        for(int i = 0; i < 10; i  )
        {
            final int j = i;
            AsyncTask<String, Integer, String> aTask =
                    new AsyncTask<String, Integer, String>()
            {
                @Override
                protected void onProgressUpdate(Integer... values)
                {
                    super.onProgressUpdate(values);
                }

                @Override
                protected String doInBackground(String... params)
                {
                    Log.e('amuro', Thread.currentThread().getName());
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    return params[0]   'done';
                }

                @Override
                protected void onPostExecute(String s)
                {
                    Log.e('amuro', 'result: '   s   ' '   j);
                }
            };
            aTask.execute('DoubleX');
        }
    }

    private void testMyAsync()
    {
        for(int i = 0; i < 10; i  )
        {
            final int j = i;

            MyAsyncTask<String, String> myTask = new MyAsyncTask<String, String>()
            {
                @Override
                protected String doInBackground(String... params)
                {
                    Log.e('amuro', Thread.currentThread().getName());
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    return params[0]   'done';
                }

                @Override
                protected void onPostExecute(String s)
                {
                    Log.e('amuro', 'result: '   s   ' '   j);
                }
            };
            myTask.execute('outSideParam ');
        }
    }
}
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

再看一下運行結(jié)果:
03-13 13:15:55.065 20514-20732/com.amuro E/amuro: MyAsyncTask #1
03-13 13:15:56.070 20514-20514/com.amuro E/amuro: result: outSideParam done 0
03-13 13:15:56.070 20514-20747/com.amuro E/amuro: MyAsyncTask #2
03-13 13:15:57.075 20514-20514/com.amuro E/amuro: result: outSideParam done 1
03-13 13:15:57.075 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:15:58.075 20514-20514/com.amuro E/amuro: result: outSideParam done 2
03-13 13:15:58.075 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:15:59.075 20514-20514/com.amuro E/amuro: result: outSideParam done 3
03-13 13:15:59.075 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:16:00.080 20514-20514/com.amuro E/amuro: result: outSideParam done 4
03-13 13:16:00.080 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:16:01.080 20514-20514/com.amuro E/amuro: result: outSideParam done 5
03-13 13:16:01.080 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:16:02.080 20514-20514/com.amuro E/amuro: result: outSideParam done 6
03-13 13:16:02.080 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:16:03.085 20514-20514/com.amuro E/amuro: result: outSideParam done 7
03-13 13:16:03.085 20514-20758/com.amuro E/amuro: MyAsyncTask #3
03-13 13:16:04.085 20514-20514/com.amuro E/amuro: result: outSideParam done 8
03-13 13:16:04.090 20514-20732/com.amuro E/amuro: MyAsyncTask #1
03-13 13:16:05.095 20514-20514/com.amuro E/amuro: result: outSideParam done 9
暴露了我的測試機弱爆了,Orz。
為了簡單起見這里就不處理onProgressUpdate了,有興趣的同學(xué)可以在這個基礎(chǔ)上自己去實現(xiàn)。我在這里總結(jié)一下execute方法執(zhí)行的整個流程。
1. 先回調(diào)了onPreExecute方法,這個是在UI線程里的。然后把外面?zhèn)魅氲膒arams賦值給了workerRunnable,其實就是FutureTask需要的Callable對象。
2. 然后就把這個FutureTask丟給了我們的defaultExecutor去執(zhí)行,這個流程和上面的例子二是一樣一樣的。
3. 執(zhí)行成功后子線程完成了結(jié)果的生成,這個時候就可以通過handler把結(jié)果丟給UI線程了。這里封裝了一個AsyncTaskResult類來傳遞結(jié)果,原因很簡單,handler是靜態(tài)對象,沒法直接拿到當(dāng)前MyAsyncTask的引用。而我們要把task和result對象同時丟給handler,所以要進(jìn)行一下封裝。
4. OK,handler拿到result之后就會把task拿出來并回調(diào)finish方法。
5. finish方法,這個時候已經(jīng)在UI線程中了,所以可以回調(diào)最終的onPostExecute方法把結(jié)果丟給client去處理了。

無論多么復(fù)雜的技術(shù)或?qū)崿F(xiàn),只要我們抓到其本質(zhì),耐心地把它涉及到的知識一點點的吃透,并多寫代碼多做測試。最終你會發(fā)現(xiàn),再復(fù)雜,不過也是小知識的層疊和擴展罷了。這和一個互聯(lián)網(wǎng)公司需要深厚的技術(shù)積累,道理也是一樣的。

就醬,謝謝觀賞~

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多