摘自:https://blog.csdn.net/qq_35572068/article/details/84961265
摘自:https://blog.csdn.net/lxg1234567890/article/details/27048949
Android主線程,也就是UI線程,其最大用途在于運作四大元件以及處理他們和使用者的互動。其他耗時操作交給子線程,如網絡請求、I/O操作,從Android3.0開始,網絡通路必須在子線程中進行,否則将會失敗并抛棄異常,避免ANR現象。
AsyncTask是輕量級異步任務類,封裝了Thread和Handler。
AsyncTask:
onPreExecute(),異步執行之前,此方法被調用做一些準備工作。doInBackground()線上程池中執行,此方法用于執行異步任務。doInBackground()線上程池中執行,此方法用于執行異步任務,執行過程中可以調用publishProgress()方法更新任務執行進度。onProgressUpdate()方法在主線程中執行,每次任務進度更新時被調用。onPostExecute()在任務執行完成時被調用,其參數為doInBackground()的傳回參數。
執行順序與聯系如下圖
代碼Demo:
public class DownloadFileAsyncTackDemo 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 );
if(isCancelled()){
break;
}
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress){
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result){
Log.d("",String.valueOf(result));
}
}
AsyncTask注意事項:
- 必須在主線程中加載,意味着第一次通路AsyncTask必須發生在主線程。
- Execute方法必須在UI線程調用。不能直接調用onPreExecute()、doInBackground()、publishProgress()、onPostExecute()、onProgressUpdate()方法。
- 一個AsyncTask對象隻能被執行一次,既隻調用一次。
- AsyncTask在4.1.1上是串行的,在2.3.3上是并行的。在3.0版本後可使用executeOnExecutor()方法啟動以實作并行。
IntentService:
IntentService是一種特殊的Service繼承自Service,任務執行後會自動停止。因為其是Service,是以優先級會比單純的線程高。且不容易被系統殺死。第一次啟動調用onCreate,每次啟動調用一次onStartCommand,在onStartCommd處理每個背景任務的Intent。
OnHandleIntent():抽象類,每次都需要實作。是處理任務的地方
每執行一個背景任務,必須啟動一次Intentservice。當有多個背景任務,按照外界發起的順序執行。
示例:
public class MyService extends IntentService {
private static final String TAG = MyService.class.getSimpleName();
private int count = 0;
public MyService() {
super(TAG);
// TODO Auto-generated constructor stub
}
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
//在這裡添加我們要執行的代碼,Intent中可以儲存我們所需的資料,
//每一次通過Intent發送的指令将被順序執行
count ++;
Log.w(TAG, "count::" + count);
}
}
在外部元件中開啟服務:在這裡我們在Activity中利用Intent循環10次開啟服務。
for (int i = 0; i < 10; i++) {
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
}
結果:
IntentService和AsyncTask有啥不同?
總結出一句話:IntentService 是Serivce+handler的結合産物 AsyncTask是thread+handler的結合産物。
為什麼用service而不用thread:
1.我們先拿 Thread 來說 ,Thread 的運作是獨立于 Activity 的,也就是說當一個 Activity 被 finish 之後 ,如果你沒有主動停止 Thread 或者 Thread 裡的 run 方法沒有執行完畢的話,Thread 也會一直執行。是以這裡會出現一個問題:當 Activity 被 finish 之後,你不再持有該 Thread 的引用。另一方面,你沒有辦法在不同的 Activity 中對同一 Thread 進行控制。
2.1 location serivce 不是一個單獨的程序,它和應用程式在同一個程序中。隻能在目前應用中調用service。kill目前應用則service也随之消亡。
2.2 remote service 獨立與應用程式之外程序的程序(必須在聲明的時候以android:process=":remote"方式聲明),配合AIDL可以實作程序間的互相調用。remote service所依附的那個應用如果應用kill掉,但是remoteservice還在運作,除非你解除安裝目前應用。
IntentService 是Serivce+handler的結合産物,可以在onHandleIntent直接處理耗時操作。而本地service和遠端service不能在onStart方法中執行耗時操作,隻能放在子線程中進行處理,當有新的intent請求過來都會線onStartCommond将其入隊列,當第一個耗時操作結束後,就會處理下一個耗時操作(此時調用onHandleIntent),都執行完了自動執行onDestory銷毀IntengService服務。
AsyncTask是thread+handler的結合産物,減少程式中線程過多開銷過大,操作和管理更加友善。AsyncTask執行個體必須在UI Thread中建立,execute方法必須在UI Thread中調用不能手動調用onPreExcute(),onPostExcute(Result)。task隻能被執行一次,否則将出現異常。