編輯:關於Android編程
首先舉個例子,獲取手機上視頻信息所需要的時間是個不能確定的事情。如果視頻很少,也許幾十毫秒就能完成,如果視頻很多(比如幾十個),也許就要花二十多秒。
安卓應用只有一個主線程-各個組件都是在這個線程中運行。作為組件的之一的Activity就是在這個線程中更新應用界面的,例如,用戶點擊界面上的一個按鈕,按鈕得到響應,整個過程就是在這個主線程裡。所以這個主線程絕對不可以做耗時的操作。假如在按鈕中做了耗時的操作,那麼當它進行耗時操作的時候,你去點擊界面上的其它按鈕是不會有反應的,就好像程序凍在了那裡。
代碼的執行一旦連續占用這個線程超過一定的時間,系統就會彈出“程序無響應的”提示。
因此,我們可以考慮把獲取視頻信息的操作放到一個單獨的線程thread中進行。
這就好比你在正在做一件事情A,突然另一件事情B來打擾你,你不得不停下手頭的工作來完成,做完了才能繼續之前的工作;這時如果有另外一個人(另一個線程)來幫助你,把事情B全部包攬了,那你就不用分心了。當另一個人把事情B做完後,告訴你一聲就可以了。
啟動一個新的線程,分擔耗時工作的方法是一種異步操作:我讓你幫我做一件事情,布置任務後,我就去做其他的事情了,等你做完了再告訴我結果;
與它對應的是同步操作:我讓你幫我做一件事情,布置任務後,我啥也不做,就等著你做完了告訴我結果;
獲取視頻信息是個異步操作,啟動一個新線程-工作線程thread-查詢視頻信息,查詢完成後,工作線程再將結果通知到主線程,讓主線程將查詢到結果的結果顯示到界面上。界面的更新一定要在主線程中進行,不能在別的線程修改,否則系統後提示運行錯誤,這一點相當重要。因此我們一定要將查詢的結果發送給主線程,讓主線程處理界面的更新。
安卓系統提供的異步操作方案有:
創建工作線程thread和Handler,利用Handler在工作線程和主線程之間傳遞數據; 使用AsyncTask幫助類,AsyncTask中封裝了工作線程,通過AsyncTask完成工作線程和主線程之間的數據傳遞;第1種方案,已經在第3節裡面介紹過了。
這裡我們介紹第2種方案。
AsyncTask實際上它也是通過方案1
實現的,只不過Android SDK對這套機制做了進一步封裝,讓使用者用起來更加方便。
AsyncTask適用於,
使用場景簡單,只是單個任務的異步操作,沒有多個線程之間的數據同步考慮; 使用方便,不用考慮太多的新線程創建的細節;AsyncTask需要被繼承成為一個新的子類來使用,在被繼承時,要指定三種參數的類型-Param
Progress
Result
,還需要實現doInBackground(Param...)
函數,此外通常還要實現onProgressUpdate(Progress...)
onPostExecute(Result)
兩個回調函數。
class MyTask extends AsyncTask {
@Override
protected Result doInBackground(Param... params) {
return result;
}
@Override
protected void onProgressUpdate(Progress... progresses) {
}
@Override
protected void onPostExecute(Result result) {
}
@Override
protected void onCancelled() {
}
}
doInBackground(Param... params)
函數:傳入參數的Param
類型就是AsyncTask
中指定的Param
類型。它運行在新創建的工作線程當中。
使用MyTask
時,要在主線程中使用excute()
方法傳入不定長參數,讓Task
運行起來,
MyTask task = new MyTask();
task.excute(param0, param1, ..., paramN);
不定長參數會以數組的形式傳遞到doInBackground()
函數當中,
@Override
protected Result doInBackground(Param... params) {
Param param0 = params[0];
Param param1 = params[1];
......
Param paramN = params[N];
return result;
}
onProgressUpdate(Progress... progresses)
函數:傳入參數的Progress
類型就是AsyncTask
中指定的Progress
類型。
在doInBackground()
中執行的是一個很耗時的工作,有時需要向主線程報告當前的運行狀況,這就要使用到publishProgress()
函數,publishProgress()
也是使用的不定長參數,
@Override
protected Result doInBackground(Param... params) {
......
publishProgress(progress1, progress2, ..., progressN)
return result;
}
不定長參數會以數組的形式傳遞到onProgressUpdate()
函數當中,
@Override
protected void onProgressUpdate(Progress... progresses) {
Progress progress0 = progresses[0];
Progress progress1 = progresses[1];
......
Progress progressN = progresses[N];
}
onPostExecute(Result result)
函數:傳入參數的Result
類型就是AsyncTask
中指定的Result
類型。
doInBackground()
函數返回的類型也是Result
@Override
protected Result doInBackground(Param... params) {
......
return result;
}
返回的結果作為參數傳遞給onPostExecute()
函數,
@Override
protected void onPostExecute(Result result) {
}
onCancel()
函數會在調用者取消AsyncTask
的工作的時候被觸發。
要取消AsyncTask
的工作,首先要在主線程中調用cancel()
方法,
task.cancel(true);
因為在doInBackground()
中執行的是一個很耗時的工作,需要時不時的檢查自己是否被取消執行了,
@Override
protected Result doInBackground(Param... params) {
......
if(isCancelled())
{
......
return result;
}
......
return result;
}
最後,onCancelled()
函數會被觸發,這個函數會在主線程中被執行,
@Override
protected void onCancelled() {
}
綜合上面的分析,自定義一個AsyncTask
的方法如下,
class MyTask extends AsyncTask {
@Override
protected Result doInBackground(Param... params) {
Param param0 = params[0];
Param param1 = params[1];
......
Param paramN = params[N];
while(!isCancelled())
{
......
publishProgress(progress1, progress2, ..., progressN);
}
return result;
}
@Override
protected void onProgressUpdate(Progress... progresses) {
Progress progress0 = progresses[0];
Progress progress1 = progresses[1];
......
Progress progressN = progresses[N];
......
}
@Override
protected void onPostExecute(Result result) {
}
@Override
protected void onCancelled() {
}
}
使用一個AsyncTask
的方法如下,
MyTask task = new MyTask();
task.excute(param0, param1, ..., paramN);
......
task.cancel(true);
轉載請注明文章出處和作者! 出處:http://blog.csdn.net/xl19862005 大家多多支持偶家媳婦的網店:http://wen1991.tao
SharedPreferences是Android中存儲簡單數據的一個工具類。可以想象它是一個小小的Cookie,它通過用鍵值對的方式把簡單數據類型(boolean、in
GridViewWithHeaderAndFooter控件,可以像使用ListView一樣為GridView添加Header和Footer。項目地址:https://gi
前言: 最近一直在看Launcher模塊,經過差不多兩個月學習,終於摸透了Launcher的一些主要功能實現,目前繼續還處於摸索狀態。未看Launcher時,於我而言,只