Android中通過AsyncTask類來制作炫酷進(jìn)度條的實例教程
AsyncTask (API level 3,所以幾乎所有目前在市面上流通的 Android 版本皆可使用)
是除 Thread 外的另一種選擇,Android 團(tuán)隊鼓勵主執(zhí)行緒(UI thread) 專注于操作 & 畫面的流暢呈現(xiàn),
其余工作 (如網(wǎng)絡(luò)資料傳輸、檔案/磁碟/資料存取) 最好都在背景執(zhí)行;
Thread 通常要搭配 Handler 使用,而 AsyncTask 用意在簡化背景執(zhí)行 thread 程序碼的撰寫。
如果您預(yù)期要執(zhí)行的工作能在幾秒內(nèi)完成,就可以選擇使用 AsyncTask,若執(zhí)行的時間很長,
Android 則強(qiáng)烈建議采用 Executor, ThreadPoolExecutor and FutureTask。
要使用 AsyncTask,必定要建立一個繼承自 AsyncTask 的子類別,并傳入 3 項資料:
- Params -- 要執(zhí)行 doInBackground() 時傳入的參數(shù),數(shù)量可以不止一個
- Progress -- doInBackground() 執(zhí)行過程中回傳給 UI thread 的資料,數(shù)量可以不止一個
- Rsesult -- 傳回執(zhí)行結(jié)果
若您沒有參數(shù)要傳入,則填入 Void (注意 V 為大寫)。
AsyncTask 的運(yùn)作有 4 個階段:
- onPreExecute -- AsyncTask 執(zhí)行前的準(zhǔn)備工作,例如畫面上顯示進(jìn)度表,
- doInBackground -- 實際要執(zhí)行的程序碼就是寫在這里,
- onProgressUpdate -- 用來顯示目前的進(jìn)度,
- onPostExecute -- 執(zhí)行完的結(jié)果 - Result 會傳入這里。
除了 doInBackground,其他 3 個 method 都是在 UI thread 呼叫
炫酷進(jìn)度條實例
我們以一個實例來說明,“點(diǎn)擊按鈕開始下載QQAndroid安裝包,然后顯示一個對話框來反饋下載進(jìn)度”。我們先初始化一個對話框,由于要顯示進(jìn)度,我們用Github上面一個能夠顯示百分比的進(jìn)度條 NumberProgressbar,啟動任務(wù)的按鈕我們使用 circlebutton,一個有酷炫動畫的按鈕,Github上面有很多非常好的開源項目,當(dāng)然炫酷的控件是其中一部分了,后面有機(jī)會,會去學(xué)習(xí)一些比較流行的控件它們的實現(xiàn)原理,今天就暫且拿來主義了~~。
1.先初始化進(jìn)度條提示對話框。
builder = new AlertDialog.Builder( MainActivity.this); LayoutInflater inflater = LayoutInflater.from(MainActivity.this); mDialogView = inflater.inflate(R.layout.progress_dialog_layout, null); mNumberProgressBar = (NumberProgressBar)mDialogView.findViewById(R.id.number_progress_bar); builder.setView(mDialogView); mDialog = builder.create();
2.設(shè)置按鈕點(diǎn)擊事件。
findViewById(R.id.circle_btn).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { dismissDialog(); mNumberProgressBar.setProgress(0); myTask = new MyAsyncTask(); myTask.execute(qqDownloadUrl); } });
3.DownloadAsyncTask實現(xiàn),有點(diǎn)長。
private class DownloadAsyncTask extends AsyncTask<String , Integer, String> { @Override protected void onPreExecute() { super.onPreExecute(); mDialog.show(); } @Override protected void onPostExecute(String aVoid) { super.onPostExecute(aVoid); dismissDialog(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); mNumberProgressBar.setProgress(values[0]); } @Override protected void onCancelled(String aVoid) { super.onCancelled(aVoid); dismissDialog(); } @Override protected void onCancelled() { super.onCancelled(); dismissDialog(); } @Override protected String doInBackground(String... params) { String urlStr = params[0]; FileOutputStream output = null; try { URL url = new URL(urlStr); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); String qqApkFile = "qqApkFile"; File file = new File(Environment.getExternalStorageDirectory() + "/" + qqApkFile); if (file.exists()) { file.delete(); } file.createNewFile(); InputStream input = connection.getInputStream(); output = new FileOutputStream(file); int total = connection.getContentLength(); if (total <= 0) { return null; } int plus = 0; int totalRead = 0; byte[] buffer = new byte[4*1024]; while((plus = input.read(buffer)) != -1){ output.write(buffer); totalRead += plus; publishProgress(totalRead * 100 / total); if (isCancelled()) { break; } } output.flush(); } catch (MalformedURLException e) { e.printStackTrace(); if (output != null) { try { output.close(); } catch (IOException e2) { e2.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); if (output != null) { try { output.close(); } catch (IOException e2) { e2.printStackTrace(); } } } finally { if (output != null) { try { output.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
這樣一個簡單的下載文件文件就基本實現(xiàn)了,到目前為止談不上技巧,但是現(xiàn)在我們有一個問題,就是如果我們的Activity正在后臺執(zhí)行一個任務(wù),可能耗時較長,那用戶可能會點(diǎn)擊返回退出Activity或者退出App,那么后臺任務(wù)不會立即退出,如果AsyncTask內(nèi)部有Activity中成員變量的引用,還會造成Activity的回收延時,造成一段時間內(nèi)的內(nèi)存泄露,所以我們需要加上下面的第四步處理。
4.onPause中判斷應(yīng)用是否要退出,從而決定是否取消AsyncTask執(zhí)行。
@Override protected void onPause() { super.onPause(); if (myTask != null && isFinishing()) { myTask.cancel(false); } }
這樣我們的異步任務(wù)就會在Activity退出時,也隨之取消任務(wù)執(zhí)行,順利被系統(tǒng)銷毀回收,第四步很多時候會被遺漏,而且一般也不會有什么致命的問題,但是一旦出問題了,就很難排查,所以遵循編碼規(guī)范還是有必要的。
相關(guān)文章
Android獲取SD卡路徑及SDCard內(nèi)存的方法
這篇文章主要介紹了Android獲取SD卡路徑及SDCard內(nèi)存的方法,較為詳細(xì)的分析了Android針對SD卡操作所涉及的類及其具體函數(shù)功能,非常具有實用價值,需要的朋友可以參考下2015-02-02Flutter?Android多窗口方案落地實戰(zhàn)
這篇文章主要為大家介紹了Flutter?Android多窗口方案落地實戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Android Room數(shù)據(jù)庫容易遇到的問題以及解決方法
這篇文章給大家介紹了我們在Android Room數(shù)據(jù)庫容易遇到的坑以及解決方法,文中有詳細(xì)的代碼示例供我們參考,具有一定的參考價值,需要的朋友可以參考下2023-09-09條件數(shù)據(jù)庫Android:sqllite的簡單使用
條件數(shù)據(jù)庫Android:sqllite的簡單使用,需要的朋友可以參考一下2013-05-05Android開發(fā)之Flutter與webview通信橋梁實現(xiàn)
這篇文章主要為大家介紹了Android開發(fā)之Flutter與webview通信橋梁實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android使用SharedPreferences存儲XML文件的實現(xiàn)方法
這篇文章主要介紹了Android使用SharedPreferences存儲XML文件的實現(xiàn)方法,實例分析了SharedPreferences類的基本初始化與文件存儲相關(guān)技巧,需要的朋友可以參考下2016-07-07