<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                之前寫過一篇Handler的源碼解析文章,因為AsyncTask底層也是Handler實現的,所以不了解的可以先去了解下Handler。本文也會再次分析下Handler,畢竟它是android源碼中隨處可見的東東。 ### 一、Handler的簡要分析 講Handler之前我們先講一下ThreadLocal的概念。簡單的說,ThreadLocal是介于局部變量和全局變量之間,可以在不同線程中互不干擾地存儲并提供數據。也就是說,變量a在A線程中值與在B線程中值可能是不同的。它通過get()和set()方法來獲取和存儲變量。 由于之前分析過Handler,在這里就大概的介紹,Handler底層是由MessageQueue和Looper去支撐。Looper可以理解為一個中介,負責論詢MessageQueue中的消息,并它消息傳給Handler進行處理。MessageQueue內部存儲結構是一個單鏈表,可以快速的插入和刪除。 在ActivityThread啟動過程中就會創建Looper并存放在ThreadLocal中,在Handler的構造方法中就會通過Looper.myLooper()去ThreadLocal中獲取該線程的Looper,接下來調用looper.prepare()方法,在該方法中創建MessageQueue,在 handler調用post或者sendMessage()時,就會調用enqueueMessage把消息存到單鏈表中,而looper.loop()方法其實就是一個死循環,一直在論詢MessageQueue,如果獲得到消息就調用target(其實就是handler)的dispatchMessage()并調用 handleMessage()進行消息處理。以上就是Handler的源碼流程,如果感興趣可以自行去跟一下。這里有一點需要強調下,就是在處理dispatchMessage()時,它的源碼如下: ~~~ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } ~~~ 只有當callback為空時才會調用handleMessage,否則調用callback.handleMessage()。這里也給我們提供了一個思路,可以通過callback來攔截消息,比如以下代碼: ~~~ private Handler H = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if(msg.what == 0x11){ return true; }else{ return false; } }}) { @Override public void handleMessage(Message msg) { //處理相應業務 }; ~~~ 這相當msg的what是0x11時,就不會再執行handleMessage了。 使用Handler有一點非常重要的,如果是在子線程使用,那需要手動的添加looper.prepare()和looper.loop()方法。而子線程handler的handleMessage也是在子線程中處理,這點需要處理。 ### 二,HandlerThread 上面即然說到在子線程中使用Handler,那我們就來說下HandlerThread,HandlerThread其實就是一個封裝好Thread,它可以使用Handler,之所以不提倡在子線程中直接使用Handler是因為它存在并發的問題。也就是說Handler在創建時需要獲取Looper對象,但此時可能Thread還沒有跑到Looper.prepare()那一步,那就會報空指針異常,看到這里我們第一反應肯定是那就用wait()和notifyAll()來實現啊。是的,HandlerThread就是加入了這兩個元素,不信可以翻下源碼: ~~~ @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } ~~~ HandlerThread在調用getLooper時,如果還不存在,就wait(),它本身是一個Thread,它在run方法創建完就會調用notifyAll(),這樣getLooper就會繼續執行。就這么簡單。實現代碼如下: ~~~ HandlerThread thread = new HandlerThread("handler"); thread.start(); Handler h = new Handler(thread.getLooper()){ @Override public void handleMessage(Message msg) { //處理相應業務 }; }; h.sendEmptyMessage(0X11); ~~~ ### 三,AsyncTask源碼分析 上面說了那么多,都是在消息處理機制,感覺有點跑題了,囧。。。接下來就來分析下AsyncTask,終于進入正題了。 **1.用法介紹** 它可以在線程池中執行后臺操作,并把進度結果傳遞給主線程。AsyncTask并不適合進行特別耗時的操作,對于耗時的任務來說建議使用線程池。 AsyncTask提供4個核心方法: **onPreExecute()**:執行前執行。 **doInBackground(Params……params)**:執行任務,可通過publishProgress方法更新任務進度,publishProgress會調用onProgressUpdate,返回計算結果給onPostExecute。 **onProgressUpdate(Progress……values)**:在主線程中執行,當后臺任務執行進度發生改變時會調用。 onPostExecute(Result result):在任務執行之間調用。 它最基本的用法如下所示: ~~~ private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls. length; long totalSize = 0; for ( int i = 0; i < count; i++) { // totalSize += Downloader.downloadFile(urls[i]); publishProgress(( int) ((i / ( float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { // setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { // showDialog("Downloaded " + result + " bytes"); } } ~~~ 好啦 ,講完用法,來分析下它的源碼吧!! **2.源碼分析** 從它的execute方法入手。 ~~~ public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } ~~~ sDefaultExecutor就是一個線程池,一個進程的所有線程都會在這個串行的線程池中排隊。接著我們進入executeOnExecutor中看看: ~~~ public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; } ~~~ 可以發現onPreExecute()最先執行。這也應驗了我們之前的分析。接下來就調用了線程池執行代碼,來看下AsyncTask線程池的實現。 ~~~ private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } } ~~~ 系統會把Params封裝成FutureTask類,這是一個并發類,相當于Runnable,接著會在SerialExcutor的execute中執行,如果沒有正在活動的AsyncTask任務,就調用scheduleNext()執行下一個,從隊列中poll對象執行,直到完成。所以它是串行的(注意,3.0以后AsyncTask是串行執行的)。 AsyncTask有兩個線程池,(serialExecutor,THREAD_POOL_EXCUTOR),serialExecutor用于任務排隊,THREAD_POOL_EXCUTOR用于執行任務。著重來看下THREAD_POOL_EXCUTOR。 ~~~ 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; ~~~ ~~~ <pre name="code" class="java">public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); ~~~ 有沒有很熟悉,上篇博客就分析過線程池的用法,它的核心線程是CPU數量+1,最大線程數是2CPU+1,超時時間是一秒。由于FutureTask的run方法會調用mWorkder的call方法,所以就調用如下代碼: ~~~ mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; ~~~ 先設置mTaskInvoked為true,表示當前任務己經被調用過了。然后執行doInBackground()方法,并把結果返回給postResult();所以子線程的業務就在doInBackground方法中執行。結果有兩種情況,后面會再講到,先來看下postResult如下: ~~~ private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; } ~~~ 看到這里就明白了,它的底層還是Handler。這里就不再分析Handler了。主要找到handler,看getHandler()的方法。 ~~~ private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } } ~~~ 很直然就進入InternalHandler()。 ~~~ private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } } ~~~ 兩種情況,一種是運行結束,調用finish,一種是還沒結束,調用onProgressUpdate傳入進度值。是不是一下子就把三個方法串起來了。好了,到這里AsyncTask的源碼就分析完了。 總結下就是AsyncTask底層由Handler來完成線程的切換,內部由線程池來執行。有兩個線程池,一個用于任務排除,一個用于線程執行。 好啦 ,就寫到這吧。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看