在Android中調用一些操作,如網絡請求,必須強制使用非UI線程,如果在UI線程當中調用就會報錯!
因此,線程操作是Android當中使用非常普遍,在線程中進行對應操作,最后把結果回傳給UI線程,由UI線程進行結果的顯示!
這里介紹兩種線程操作!
這種方法是最原始,也是最靈活的方式,完全沒有被封裝,但是使用起來相對也復雜一些!
主要的步驟為:
1)創建Handler,用於接收線程完成后回傳的結果
private Handler resultHandler = new Handler() { @Override public void handleMessage(Message msg) { // 關閉加載控件 if(progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } // 處理返回結果 if(msg.what == 0) { // 調用成功,顯示結果 ResultData resultData = (ResultData) msg.obj; tv_name.SetText(resultData.name); } else { // 調用失敗 String err = (String) msg.obj; Toast.makeText(context, err, Toast.LENGTH_SHORT).show(); } } }
2)創建Thread,在當中進行耗時操作
// 調用前顯示加載控件 progressDialog = ProgressDialog.show(ReservationListActivity.this, "提示", "正在加載數據..."); // 開始線程並加載數據 new Thread(new Runnable() { @Override public void run() { // 線程處理過程 ... // 返回成功結果 ResultData resultData = new ResultData(); resultData.name = "張三"; Message msg = Message.obtain(); msg.what = 0; msg.obj = resultData; resultHandler.sendMessage(msg); // 返回失敗結果 Message msg = Message.obtain(); msg.what = -1; msg.obj = "結果不存在"; resultHandler.sendMessage(msg); } }).start();
這種方法其實比較簡單,通過Thread執行耗時操作,在操作完成后,向Handler發送消息,同時把結果傳遞進去;
之后Handler接收到傳遞過來的消息,根據消息的內容進行不同的處理,如成功、失敗等!
多個Thread的返回可以共用一個Handler,只需要在結果那里處理好區分即可。
也有許多人將此操作封裝成一個類,這樣調用起來更簡便,原理是一樣的。
這種方法是Google推薦的方法,原理與Thread+Handler類似,但是Google進行了封裝,使用起來更方便一些。
使用時,需要對AsyncTask進行繼承,其原型為:AsyncTask<Params,Progress,Result>,這里需要說明一下:
Params 啟動任務時輸入的參數類型
Progress 后台任務執行中返回進度值的類型
Result 后台任務執行完成后返回結果的類型
這樣傳參,進度,返回都已經包含在內了,如果傳參,返回的數據較復雜,可定義為類進行傳輸
AsyncTask主要的重載函數包括:
doInBackground 必須重寫,異步執行后台線程要完成的任務,耗時操作將在此方法中完成.
onPreExecute 執行后台耗時操作前被調用,通常用於進行初始化操作.
onPostExecute 當doInBackground方法完成后,系統將自動調用此方法,並將doInBackground方法返回的值傳入此方法.通過此方法進行UI的更新.
onProgressUpdate 當在doInBackground方法中調用publishProgress方法更新任務執行進度后,將調用此方法.通過此方法我們可以知曉任務的完成進度.
一般我們只需要用到 doInBackground 和 onPostExecute。
// 調用前顯示加載控件 progressDialog = ProgressDialog.show(ReservationListActivity.this, "提示", "正在加載數據..."); // 這里定義輸入參數為String類型,輸出參數為ReaultData類型 new AsyncTask<String, Void, ReaultData>(){ // 在后台執行的過程函數,所有耗時操作放在此函數中執行 @Override protected AsyncFilesData doInBackground(String... params) { // params 即傳入的參數,此例中就是 "http://www.abc.com/api/getinfo?id=10" url = params[0]; // 定義返回結果對象 ResultData resultData = new ReaultData(); try { String str = geturl(url); resultData = JSONObject.parseObject(str, ResultData.class); return resultData; } catch(Exception ex) { resultData.result = -1; resultData.msg = ex.getMessage(); return resultData; } } // doInBackground返回結果后會自動調用此函數 // 此函數是在 UI 線程當中被調用,因此可將對UI的操作放在當中執行 @Override protected void onPostExecute(ResultData resultData) { // 關閉加載控件 if(progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } // 處理返回結果 if(resultData.result == 0) { // 調用成功,顯示結果 tv_name.SetText(resultData.name); } else { // 調用失敗 String err = resultData.msg; Toast.makeText(context, err, Toast.LENGTH_SHORT).show(); } } // 傳入的參數是調用一個Webapi獲取指定ID的info }.execute("http://www.abc.com/api/getinfo?id=10");
AsyncTask的優勢是書寫簡單,且 onPostExecute 已在UI線程當中,不必再處理線程向UI線程同步問題。
這就是今天介紹的兩種線程調用同步方法!
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。