學習筆記(一)多執行緒與服務的一般操作
Android中,當需要進行一些耗時操作時,常常需要開啟一個多執行緒來進行耗時操作,但是當要進行UI操作時則需要在主執行緒中進行,因此這就涉及到了程序間的切換.
1.1 非同步訊息處理機制(Handler)
主執行緒定義Handler,並重寫handlerMessage()方法,當開啟一個執行緒並對其進行耗時操作結束後,要想跳轉到主執行緒進行UI操作時,則需要定義一個Message訊息,然後用handler把訊息發出去,並在handlerMessage()中進行接收處理,從而實現非同步.
解析非同步訊息處理機制:
- Message:線上程之間傳遞的訊息,可攜帶少量的資訊,線上程之間進行資料交流
- Handler:處理者,用來發送和處理訊息
- MessageQueue:訊息佇列,用來存放所有通過Handler傳送的訊息,這些訊息會被一隻存放在訊息佇列中,等待被處理,每個執行緒只有一個訊息佇列
- Looper:是每個訊息佇列的管家,當呼叫Looper的loop()方法後,就會進入一個無限迴圈中,每當發現訊息佇列中存在一個訊息,就會把它取出來,並傳遞到Handler的handlerMesseage()方法中,進行訊息的發出,每個執行緒中只會有一個Looper物件
1.2 使用AsyncTask
asyncTask是Android提供的一個方便我們在子執行緒中進行UI操作的工具,它背後實現的原理也是基於非同步訊息處理機制,只是Android為我們做了一個很好的封裝.
使用時繼承AsyncTask,並重寫相應的方法,如下:
/** * AsyncTask方便在子執行緒中執行UI操作,基於非同步訊息處理機制 * 泛型引數一:執行AsyncTask時需要傳遞的引數 * 泛型引數二:後臺執行任務時,要顯示的進度單位 * 泛型引數三:執行完畢後的返回值單位 */ public class MyDownloadTask extends AsyncTask<String, Integer, Integer>{ /** * 會在後臺任務開始執行前呼叫,通常用來執行一些介面上的初始化工作,如顯示一個進度條對話方塊等等 */ @Override protected void onPreExecute() { super.onPreExecute(); } /** * 後臺處理耗時任務,在子執行緒中進行,不可以進行UI操作 * * @param strings 繼承AsyncTask時的第一個泛型引數 * @return 將任務的執行結果返回 */ @Override protected Integer doInBackground(String... strings) { return 0; } /** * 當在後臺任務中呼叫了publicProgress方法後,會得到呼叫 * 在此方法中可以進行UI操作 * * @param values 後臺任務傳遞的引數 */ @Override protected void onProgressUpdate(Integer... values){ } /** * 當任務執行完畢並通過return返回時,會得到呼叫 * 不在子執行緒中,可以進行UI操作 * * @param integer return返回的資料 */ @Override protected void onPostExecute(Integer integer) { } } 複製程式碼
2 服務(主要討論與活動的交流)
服務也屬於四大元件之中的一種,所以建立一個服務時也要在清單檔案中註冊才能夠進行使用
2.1 開啟服務
-
startService:開啟服務,服務開啟後就與活動無關了,會在後臺一直執行,除非手動呼叫了stopService()才能停止服務
-
bindService:繫結服務,通過繫結服務可以將活動與服務聯絡起來,並進行通訊,通過Binder和ServiceConnection實現;
2.2 實現服務與活動的交流
- 首先在服務中建立一個繼承Binder的類例項,並在這個類中定義想要跟活動進行交流的方法,並通過服務重寫的onBind()方法返回這個binder例項給活動
private DownloadBinder mBinder = new DownloadBinder(); /** * 通過Binder實現服務與活動的資訊交流 */ public class DownloadBinder extends Binder{ //想要和服務進行交流的方法 public void startDownload() { } } @Nullable @Override public IBinder onBind(Intent intent) { //把建立的binder傳到活動,使得活動可以呼叫 return mBinder; } 複製程式碼
- 在要進行交流的活動中建立一個ServiceConnection物件,並重寫onServiceConnected()方法(當服務與活動成功進行繫結後呼叫),然後在此方法中通過服務傳過來的IBinder物件向下轉型得到我們想要的binder物件
/** * 服務與互動進行交流的工具 */ private MyDownloadService.DownloadBinder downloadBinder; private MyServiceConnection myServiceConnection = new MyServiceConnection(); /** * 用做服務與活動進行交流的橋樑 */ class MyServiceConnection implements ServiceConnection { /** * 當服務與活動成功進行繫結時呼叫 * * @param service 所繫結的服務對應的Binder */ @Override public void onServiceConnected(ComponentName name, IBinder service) { //獲得Binder物件,便可以進行與服務的交流 downloadBinder = (MyDownloadService.DownloadBinder) service; } /** * 當服務與活動斷開連線時呼叫 */ @Override public void onServiceDisconnected(ComponentName name) { } } 複製程式碼
- bindService()時需要把ServiceConnection物件也傳入進去
//繫結服務,引數三:當繫結成功後自動建立服務的標誌 bindService(intent, myServiceConnection, BIND_AUTO_CREATE); 複製程式碼
- 通過binder物件便可以呼叫服務中寫好的方法,從而實現服務與活動的交流
downloadBinder.startDownload(); 複製程式碼