AsyncTask是一種不屬於主線的執行緒,目的在於提供簡單易用的方式來達成Handler+Thread的功能,因為它已經有寫好了的方法,因此在使用上會比自己重新寫Handler和Thread較為方便,比較適合進行短時間的執行緒工作。使用方法如下:
(一)建立一個內部或外部類別Thread繼承至AsyncTask這個thread,AsyncTask要定義的參數為<Params,Progress,Result>,第一個參數Params 為啟動任務時要傳入的資料類型,第二個參數為Progress為背景活動的進度類型,而第三個參數為Result類型為執行返回的結果。如果沒有要傳入,可用Void,如AsyncTask<Void, Void, Void>。
如下:
class mythread extends AsyncTask<String , Integer , Bitmap>{ }(二)修改AsyncTask預設的方法中的內容,方法依序有onPreExecute doInBackground
onProgressUpdate onPostExecute等等的內容,如果沒有用到可以不修改。
(1)onPreExecute為執行AsyncTask背景活動前要做的事。
(2)doInBackground中的程式為你希望在背景默默執行的工作。其中的參數String... params為一陣列清單,params[0]可取出第一個參數值,其餘依此類推。此處的內容只在背景執行,因此不要在此處直接更新主執行序的介面。
(3)onProgressUpdate 在背景程式時,要手動呼叫的活動。如果要背景執行時,持續的更新主執行緒的數據,像是 執行進度條,又或是時間倒數等資訊,就可以將程式放在此處。其中的參數Integer... values也是陣列清單,values[0]可取出第一個參數值,其餘依此類推。
(4)onPostExecute 此處為進行完,你要執行的背景活動後,要執行的程式活動。
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private ImageView imageView; //宣告imageview準備放圖片的地方
private ProgressBar pgBar; //宣告進度表
private Button button; //宣告button,點選後開啟
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=findViewById(R.id.imageView); //從xml取得imageview
pgBar=findViewById(R.id.pgbar); //從xml中取得progressbar
button=findViewById(R.id.button); //從xml中取得button
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mythread task = new mythread(MainActivity.this,pgBar,imageView); //宣告task為自己新建一個thread,其中的參數第一個為MainActivity,第二個為進度軸,第三個為imageview,把這三個參數傳入thread,以便控劉
task.execute("https://images.pexels.com/photos/11319741/pexels-photo-11319741.jpeg?cs=srgb&dl=pexels-mathilde-langevin-11319741.jpg&fm=jpg"); //讓thread啟動,參數為網路的圖片網址,targetSdkVersion27版本以上不能用http連接,要用https
}
});
}
//結束後,釋放資料
@Override
protected void onDestroy() {
super.onDestroy();
imageView.setImageBitmap(null);
}
}
//自己建立的thread執行緒,命名為mythread
class mythread extends AsyncTask<String , Integer , Bitmap>{
private ImageView imageView; // 宣告imageview,以對應主執行緒丟過來的imageview
private Context context;
private ProgressBar progressBar; // 宣告progressBar,以對應主執行緒丟過來的progressBar
private Object Integer;
//mythread的建構式,參數有context, progressBar, imageView
public mythread(Context context,ProgressBar progressBar,ImageView imageView) {
this.context = context; //將傳入的數值於類別的數值相互綁定
this.progressBar=progressBar;
this.imageView=imageView;
}
//在此設定執行執行緒前要做的設定
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE); //進度表顯現
imageView.setVisibility(View.GONE); //於主畫面中隱藏imageview
//初始化進度條並設定樣式及顯示的資訊。
}
//執行序要跑的工作在此運作,params為執行任務
@Override
protected Bitmap doInBackground(String... params) {
int progress = 0;
publishProgress(0);
String urlStr = params[0];
try {
URL url = new URL(urlStr);
publishProgress(50);
//progressBar.setProgress(50);
Log.v("acao", "1");
return BitmapFactory.decodeStream(url.openConnection().getInputStream()); //將取得的bitmap檔return回去,於結果裡運用
} catch (Exception e) {
e.printStackTrace();
progressBar.setProgress(50);
Log.v("acao", "2");
//最後達到100%
return null;
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
//在doInBackground中,若呼叫publishProgress的時候會在這裡告知使用者進度,配合progressBar.setProgress,可以控制進度條
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
imageView.setVisibility(View.VISIBLE); //當完成的時候,顯示imageview
progressBar.setVisibility(View.GONE); //當完成的時候,隱藏進度條
imageView.setImageBitmap(bitmap); //將讀取的bitmap放在imageview
//執行完的設定
}
(三)呼叫的方法是在主執行序執行,如果只是一次使用,可以使用:
new thread().execute;
如果說要多次使用,可用下列的方法。
mythread task = new mythread(要丟入的參數);task.execute("https://images.pexels.com/photos/11319741/pexels-photo-11319741.jpeg?cs=srgb&dl=pexels-mathilde-langevin-11319741.jpg&fm=jpg");
補充:thread中是否給值,要看你於mythread裡的建構式,public mythread(Context context,ProgressBar progressBar,ImageView imageView),有沒有給予值,如上面例子就要給予三個值;而execute裡是否要有值,要看之前在AsyncTask<Void, Void, Void>中的設定,如果是Void就不用給值,而如果是有加入型態,就依你加入的型態給與適當的值。
參考網址:
http://aiur3908.blogspot.com/2015/06/android-asynctask.html
https://oldgrayduck.blogspot.com/2013/01/androidasynctask-thread.html
https://www.aiwalls.com/android軟體開發教學/15/2156.html
https://dotblogs.com.tw/hanktom/2016/01/26/191154
沒有留言:
張貼留言