Android中使用Handler和异步任务(AsyncTack)来为UI线程执行费时操作
出于性能優(yōu)化的考慮,Android的UI線程不是線程安全的。這致使我們不能在Android的UI線程中執(zhí)行一些費(fèi)時的操作,如下載、刷新等。Android中只允許UI線程對Activity中的UI組件進(jìn)行修改。
不過我們可以新建一條線程來代替UI線程執(zhí)行這一操作,在Android中可以借助于Handler的消息傳遞機(jī)制來實(shí)現(xiàn)。
Handler類的兩個主要作用:
1)在新啟的線程中發(fā)送消息;
2)在主線程中獲取和處理消息。
我們利用Handler的這兩個作用,可以先在主線程中新建一條新的輔助線程,并且在這條新的線程中執(zhí)行發(fā)送消息。這個消息就是我們通知系統(tǒng),說現(xiàn)在需要更新UI界面了。如下:
new Timer().schedule(new TimerTask() {@Overridepublic void run() {handler.sendEmptyMessage(0x1233);}}, 0, 1000);
上面的代碼重寫了Handler的sendMessage(Message msg),不過在這里使用的是sendEmptyMessage(int what),因?yàn)檫@里只是通知主線程更新界面,沒有過多的其他操作,所以只需要發(fā)送一條空的消息即可。若是更新的內(nèi)容比較多或是一些其它的限制不能只發(fā)送一條空消息就能解決,那就應(yīng)該發(fā)送一些有實(shí)質(zhì)內(nèi)容的東西,而這咱消息內(nèi)容是Object的類型。對于Object這種類型的消息,是一個很寬泛的類型,它能裝載的內(nèi)容太多了。這個時候需要使用sendMessage(Message msg)。廢話有點(diǎn)多,見諒。。。
那么當(dāng)主線程拿到這條消息時,就會對其進(jìn)行處理:
Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 0x1233) {((ImageView) findViewById(R.id.imageView1)).setImageResource(imageId[(currentImg++) % imageId.length]);}}};以上就是簡單地使用Handler來處理UI線程不安全問題。具體的代碼實(shí)現(xiàn)還有不發(fā)送空消息來更新界面的代碼以及AsyncTask的代碼,我會在下面的給出連接。
-------------------------------------------------------------------------------------------------------------------------------------------------------
下面我們再來看看異步任務(wù)(AsyncTask)的簡單用例。
使用AsyncTask需要有如下三個步驟:
1)創(chuàng)建AsyncTask的子類,并為其三個泛型參數(shù)指定類型。如果某個泛型參數(shù)不需要指定類型,則用void代替;
2)根據(jù)需要,實(shí)現(xiàn)AsyncTask的以下幾個方法:
Ⅰ.doInBackground(Params...)這個方法,就是AsyncTask子類執(zhí)行異步任務(wù)內(nèi)容的方法;
Ⅱ.onProgressUpdate(Progress...)這個方法,會在執(zhí)行完上一個方法后,被調(diào)用;
Ⅲ.onPreExecute()這個方法會在我們執(zhí)行費(fèi)時操作之前被調(diào)用,用于處理一些準(zhǔn)備工作,如初始進(jìn)度條什么的;
Ⅳ.onPostExecute()當(dāng)doInBackground()執(zhí)行完成之后,系統(tǒng)會自動調(diào)用該方法,并把doInBackground()執(zhí)行的結(jié)果返回給該方法。
3)最后一步就是,我們在主線程中調(diào)用AsyncTask實(shí)例的execute(Params ... param)方法,表示開始執(zhí)行費(fèi)時操作。
如下代碼:
class DownTask extends AsyncTask<URL, Integer, String> {// 可變長的輸入?yún)?shù),與AsyncTask.exucute()對應(yīng)ProgressDialog pdialog;// 定義記錄已經(jīng)讀取行的數(shù)量int hasRead = 0;Context mContext;public DownTask(Context ctx) {mContext = ctx;}@Overrideprotected void onPreExecute() {pdialog = new ProgressDialog(mContext);pdialog.setTitle("任務(wù)正在執(zhí)行中");pdialog.setMessage("任務(wù)正在執(zhí)行中,敬請等待...");// 設(shè)置對話框不能用“取消”按鈕關(guān)閉pdialog.setCancelable(false);// 設(shè)置該進(jìn)度條的最大進(jìn)度值pdialog.setMax(202);// 設(shè)置對話框的進(jìn)度條風(fēng)格pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 設(shè)置對話框的進(jìn)度條是否顯示進(jìn)度pdialog.setIndeterminate(false);pdialog.show();}@Overrideprotected String doInBackground(URL... params) {StringBuilder sb = new StringBuilder();try {URLConnection conn = params[0].openConnection();// 打開conn連接對應(yīng)的輸入流,并將它包裝成BufferedReaderBufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));String line = null;while ((line = br.readLine()) != null) {sb.append(line + "\n");hasRead++;publishProgress(hasRead);}return sb.toString();} catch (Exception e) {e.printStackTrace();}return null;}@Overrideprotected void onProgressUpdate(Integer... values) {// 更新進(jìn)度show.setText("已經(jīng)讀取了【" + values[0] + "】行!");pdialog.setProgress(values[0]);}@Overrideprotected void onPostExecute(String result) {// 返回HTML頁面的內(nèi)容show.setText(result);pdialog.dismiss();}}
關(guān)于Handler和AsyncTack的使用就簡單介紹到這里。 本篇博客主要參考資料是《瘋狂Android講義》第3章內(nèi)容。
----------------------------------------------------------點(diǎn)擊進(jìn)行源碼的下載連接 -----------------------------------------------------------
總結(jié)
以上是生活随笔為你收集整理的Android中使用Handler和异步任务(AsyncTack)来为UI线程执行费时操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在ListView中使用BaseAdap
- 下一篇: Android Wifi开发之WifiC