1. 程式人生 > >設計模式---模板方法模式和AsyncTask的原始碼分析

設計模式---模板方法模式和AsyncTask的原始碼分析

定義:定義一個操作中的方法的框架,將這些方法的具體的實現延遲到子類中實現, 使得子類能夠不改變演算法的結構就能重新定義演算法的內容。也就是流程封裝。 使用場景:程式碼執行的流程是固定的,也就是我們常用的將各個方法抽取的到父類中,然後通過鉤子函式進行約束子類中的行為。我們常用的BaseActivity,BaseFragment等都是使用這種設計模式。 優點:封裝不變的部分,擴充套件可變的部分。提取公共的方法,方便進行維護。 缺點:可能影響程式碼的閱讀。

AsyncTask的原始碼分析 1.使用 在這裡插入圖片描述 2.初始化構造器 這裡傳遞的引數是null 在這裡插入圖片描述 因此mHandler被賦值為getMainHandler(), 並建立WorkerRunnable和FutureTask類。 在WorkerRunnable中的call()方法中呼叫doInBackground()方法。這個方法可以由使用者自己實現。然後呼叫了postResult(result)方法,傳送handler。 在這裡插入圖片描述

在這裡,mFuture包裹mWorker的物件。 在這裡插入圖片描述 3. 內部handler類-----InternalHandler類,就是一個自定義的handler類 在這裡插入圖片描述 在這裡進行獲取我們使用AsyncTask的引數,並且只取了第一個引數。 在這裡插入圖片描述 4.呼叫AsyncTask的execute(params)方法.這裡是方法進行執行的入口。 在這裡插入圖片描述 上面的sDefaultExecutor是SerialExecutor()的例項。這裡的ArrayDeque就是自定義的16位的陣列。在這裡的mTasks.offer()方法就是向陣列中新增一條資料。然後在run()方法中,呼叫r引數的run()方法。這裡的r在下面的方法中能夠看到。呼叫schedulerNext()方法,在mTasks.poll()取出存放的資料,然後呼叫THREAD_POOL_EXECUTOR.execute()方法。 這裡的THREAD_POOL_EXECUTOR就是執行緒池的物件。 在這裡插入圖片描述
這裡使用了執行緒池。要研究執行緒的原始碼 在這裡插入圖片描述 5.呼叫executeOnExcutor()方法。在這裡mStatus預設就是PENDING,但是這個mStatus在程式碼的執行中是在改變的,因此asyncTask的例項呼叫excute()方法只能呼叫一次。因為如果重複呼叫這裡的mStatus已經發生改變,會報異常。 在這裡設定mStatus的狀態。然後呼叫onPreExecute()方法。呼叫exec.execute(mFuture)方法,這裡傳進去的是mFuture物件。可以在前幾張圖中發現是呼叫scheduleNext()方法。然後呼叫執行緒池的execute()方法。 在這裡插入圖片描述 6.呼叫執行緒池的execute()方法。根據下面的英文的註釋,很明顯的知道線上程池中處理任務就會自動的開啟執行緒。 在這裡插入圖片描述
在這裡插入圖片描述 其中最重要的就是呼叫addWorker()方法,在這裡才是真正的建立執行緒。 在addWorker()中最重要的方法。 在這裡插入圖片描述 在Worker()的構造器中就看到了執行緒的建立。 在這裡插入圖片描述 7.線上程池中要呼叫的是mFuture的run()方法。這時候就會呼叫callable的call()方法。這裡的callable就是傳遞過去的mWorker物件。然後在set(result)中會呼叫自己的done()方法。 在這裡插入圖片描述 8.建立WorkerRunnable類實現Callable介面,並且添加了mParams引數。 在這裡插入圖片描述 在這裡插入圖片描述 在WorkRunnable()的call()方法中,最終會呼叫postResult()方法。這裡的getHandler()就獲取了上面的InternalHandler的物件。然後進行傳送handler訊息,然後進行訊息的處理。注意在這裡傳遞的引數是AsyncTaskResult()的物件。 在這裡插入圖片描述 在AsyncTaskResult()的物件中,封裝了兩個引數,其中第一個就是當前的AsyncTask的物件,第二個其實就我們傳遞過來的可變引數。 在這裡插入圖片描述 5.處理handler訊息, 最終呼叫的是當前的AsyncTask物件的finish()方法。在這裡如果是取消,那麼就會呼叫onCancelled()方法,否則就會呼叫onPostExecute()方法。 在這裡插入圖片描述