前言
現在下載東西大多都使用第三方套件,異步任務都已經幫你處理得妥妥的。但如果你要生成一張很大的圖片或是很好資源的任何東西,你就會需要它
這邊貼個介紹
http://aiur3908.blogspot.tw/2015/06/android-asynctask.html
超好懂的AsyncTask
以下簡略轉貼
求詳細請點上面網址
今日實作
重點程式碼
AsyncTask<Params, Progress, Result>你開的class 會需要繼承 AsyncTask
而後面的三個參數
Params 代表著你要放入的參數,像是String 或是 int
Progress 如果你要下載東西,這邊專門給你用進度條的參數
Result 就是你希望這條你新分出去的執行緒要回到主執行緒的時候要返回什麼東西。
如果你是拿來下載圖片,就可以返回Bitma。如果你是跑一個陣列,也可以返回ArrayList<>之類的....
而繼承AsyncTask會產生四個方法
onPreExecute 執行前,一些基本設定可以在這邊做。
doInBackground 執行中,在背景做任務。這邊就是重點中的重點,你希望下載或做事情的方法寫在這邊
onProgressUpdate 執行中,專門給Porgress條做監聽的方法
onPostExecute 執行後,最後的結果會在這邊。如果你Result的部分設定返回圖片,這裡就會噴Bitmap給你
方法會長以下這樣
private class GetImage extends AsyncTask<String , Integer , Bitmap>{ @Override protected void onPreExecute() { //執行前 設定可以在這邊設定 super.onPreExecute(); } @Override protected Bitmap doInBackground(String... params) { //執行中 在背景做事情 return null; } @Override protected void onProgressUpdate(Integer... values) { //執行中 可以在這邊告知使用者進度 super.onProgressUpdate(values); } @Override protected void onPostExecute(Bitmap bitmap) { //執行後 完成背景任務 super.onPostExecute(bitmap); } }
String... 和 int... 的部分可以參考我寫的一篇猛虎出閘
http://nikeru8.blogspot.tw/2017/08/java.html
如果是複數的Params,使用方式就是Params[0]、Params[1]依此類推...
Params[0] 就會是helloOne
Params[1] 就是 helloTwo
使用範例
private class GetImage extends AsyncTask<String , Integer , Bitmap>{ private ProgressDialog progressBar; //進度條元件 @Override protected void onPreExecute() { //執行前 設定可以在這邊設定 super.onPreExecute(); progressBar = new ProgressDialog(MainActivity.this); progressBar.setMessage("Loading..."); progressBar.setCancelable(false); progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressBar.show(); //初始化進度條並設定樣式及顯示的資訊。 } @Override protected Bitmap doInBackground(String... params) { //執行中 在背景做事情 int progress = 0; for (String urlStr : params) { try { URL url = new URL(urlStr); Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream()); } catch (Exception e) { e.printStackTrace(); } publishProgress(progress+=33); //有三張圖 每張圖33% } publishProgress(100); //最後達到100% return null; } @Override protected void onProgressUpdate(Integer... values) { //執行中 可以在這邊告知使用者進度 super.onProgressUpdate(values); progressBar.setProgress(values[0]); //取得更新的進度 } @Override protected void onPostExecute(Bitmap bitmap) { //執行後 完成背景任務 super.onPostExecute(bitmap); progressBar.dismiss(); //當完成的時候,把進度條消失 imageView.setImageBitmap(bitmap); } }
完整程式碼
main_activity.xml<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:clickable="true" android:gravity="center" android:onClick="onbuttonclick" android:text="產生QRCode" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button" android:layout_centerHorizontal="true" android:layout_marginTop="45dp" /> </RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity { private Activity activity; private ProgressDialog loadingDialog; //要生成的QRCode內容 String QRCodeContent = "http://nikeru8.blogspot.tw/2017/04/third-partyxzingcore-qrcodejar.html"; ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; //參數 imageView = (ImageView) findViewById(R.id.imageView); //設定loading Dialog loadingDialog = new ProgressDialog(activity); loadingDialog.setCanceledOnTouchOutside(false); loadingDialog.setCancelable(true); loadingDialog.setMessage("loading please wait..."); } public void onbuttonclick(View view) { new GetImage().execute(QRCodeContent); } private class GetImage extends AsyncTask<String, Integer, Bitmap> { @Override protected void onPreExecute() { //執行前 設定可以在這邊設定 loadingDialog.show(); super.onPreExecute(); } @Override protected Bitmap doInBackground(String... params) { //執行中 在背景做事情 int QRCodeWidth = 600; int QRCodeHeight = 600; //QRCode內容編碼 Map hints = new EnumMap(EncodeHintType.class); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); MultiFormatWriter writer = new MultiFormatWriter(); try { //ErrorCorrectionLevel容錯率分四級:L(7%) M(15%) Q(25%) H(30%) hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //建立QRCode的資料矩陣 BitMatrix result = writer.encode(params[0], BarcodeFormat.QR_CODE, QRCodeWidth, QRCodeHeight, hints); //建立矩陣圖 Bitmap bitmap = Bitmap.createBitmap(QRCodeWidth, QRCodeHeight, Bitmap.Config.ARGB_4444); for (int y = 0; y < QRCodeHeight; y++) { for (int x = 0; x < QRCodeWidth; x++) { bitmap.setPixel(x, y, result.get(x, y) ? Color.BLACK : Color.WHITE); } } return bitmap; } catch (WriterException e) { e.printStackTrace(); return null; } } @Override protected void onProgressUpdate(Integer... values) { //執行中 可以在這邊告知使用者進度 super.onProgressUpdate(values); } @Override protected void onPostExecute(Bitmap bitmap) { //執行後 完成背景任務 super.onPostExecute(bitmap); imageView.setImageBitmap(bitmap); loadingDialog.dismiss(); } } }
Demo
我拿QRCode寫個範例
因為QRCode如果跑太大張,通常都會造成畫面卡頓
使用AsyncTask就可以完美解決這問題
https://github.com/nikeru8/QRCodeDemo
對我有很大的幫助!!! 謝謝你~
回覆刪除