AsyncTask,顧名思義,異步任務。說到異步,最簡單的理解就是不同步。再復雜一點理解,就得舉例子了。
假設我要去火車站買票,剛到火車站我突然發現我忘了帶身份證。怎么辦?怎么辦!
想辦法,想辦法!我想我應該找個在學校的同學幫我送過來,因為我不能自己回去拿啊,還要排隊呢,走不開。嗯,要找人送過來。但是問題來了,我找人送身份證了,我去排隊了,如果排到第一位了身份證還沒到怎么辦?叮,腦袋上面突然亮了一個小燈泡,機智的我在排隊前想到了兩種方案:
第一種方案,讓售票員等著我,我后面隊伍里買票的人也等著我,我一直在窗口第一位置等著同學來送身份證,直到,我的身份證被送來,然后順利買票。
另一種方案呢,就是我跟售票員說一下,讓我在一邊等著送身份證,后面的人繼續買票,等我的身份證送來的時候我通知下售票員,就可以盡快排到隊伍第一位(不一定是立即排到第一位,因為萬一有人正在買票,我不能過去打斷他)然后買票。
所以呢,選第一種還是第二種?我肯定選第二種,因為選第一種肯定會被后面排隊的人罵死,而且還有可能被售票員罵,搞不好還會挨揍,畢竟因為我一個人,浪費了這么多人的時間,也拖慢了售票員的工作效率。
好了,例子就說到這里。在例子里,第二種方法就是異步的。異步往往和多線程有關,而且異步任務也大多是交由一個單獨的線程完成,然后返回結果給主線程。這里售票員相當于cpu,而排隊買票的人相當于等待被執行的任務,而我是個被標記為異步的任務(因為我知道我帶身份證,不能立即買到票,所以排隊前就想好了第二種方案),當cpu執行到我這個任務的時候,發現我這個任務可執行的條件(身份證)不具備,所以由我發起了一個異步任務(同學送票),去獲取可執行的條件,之后立即把位置讓出來,讓其他排隊的任務繼續執行。直到我的身份證拿來,然后立馬通知cpu準備接待我。
嗯,差不多就是這樣了。開始說正文,android里面的AsyncTask。先上一段官網的引用:
是英語,雖然我能懂大概是什么意思,但是還是不翻譯了,怕誤人子弟,等我英語學的再好些再來翻譯吧。不過還是要解釋下大概的意思,就是說AsyncTask可以在UI線程上做一些后臺操作,也能返回操作結果到UI線程上。我們知道UI線程是不能做一些耗時的操作的,但是有了AsyncTask,我們可以這樣做了。但是,
對于耗時比較久的任務,還是不建議放在AsyncTask中執行。AysncTask被設計成Thread和Handler的輔助類,并不能執行過于復雜和耗時的任務,這種任務應該用其他方法這里就不說了。AsyncTask最好用于耗時最多只有幾秒鐘的操作,比如向網絡請求個xml或是json之類的網絡操作,或是用在程序的初始化界面等等。
下面說下AsyncTask的使用。其實很簡單。
首先你需要定義一個AsyncTask的子類,并且必須重寫父類的doInBackground(Params...)方法。另外還有onPostExecute(Result)方法也可重寫,這個方法在doInBackground之后被自動調用,所以你可以在這里寫一些任務完成的通知代碼。
先給一個官方的例子:
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"); } }
執行AsyncTask的時候,必須在UI線程中執行,如下語句。
new DownloadFilesTask().execute(url1, url2, url3);
可以看到,在繼承AsyncTask的時候,有幾個泛型類型,如AsyncTask<URL, Integer, Long>,簡單解釋下。
第一個可以指定輸入參數的類型,就是new DownloadFilesTask().execute()的參數(最后傳到了doInBackground),這里的參數可以不只一個,因為最后到方法里面,收到的是個數組。
第二個可指定發送進度更新需要的類型,一般都是整型,用在publishProgress(用來在后臺進程中發送進度的方法,直接使用的,不用定義)和onProgressUpdate兩個方法中。
第三個是AsyncTask返回結果的數據類型,它設置了doInBackground的返回類型,以及onPostExecute的輸入參數類型
當然,如果你什么都不需要,可以都使用Void。
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
另外,還有一個可以重寫的方法,是onPreExecute(),它在doInBackground之前被調用,所以如果需要的話,你可以重寫它然后做一些實例化進度條啊之類的工作。
最后,總結一下:
使用AsyncTask,你要做的是,繼承父類,然后重寫doInBackground(Params...),在里面實現后臺操作,如果有返回結果的話,重寫onPostExecute(Result)然后處理后臺程序的結果。
如果需要更新進度的話,在onPreExecute()里實例化進度條(也可以不在這),之后在doInBackground(Params...)里面用publishProgress()發布進度值,然后重寫onProgressUpdate(Progress...)接收onPreExecute()發布的結果,并添加更新進度條的代碼。
以上就是關于Android中異步任務的內容了,希望大家能夠喜歡。
新聞熱點
疑難解答
圖片精選