前言
第一次寫文章围段,記錄下自己新手Android路上的開發(fā)點(diǎn)滴,之前學(xué)過AsyncTask基本使用芋忿,記錄一下炸客,要不然老是忘記。如有發(fā)現(xiàn)不對(duì)的地方也請(qǐng)多多指教戈钢。
正文
AsyncTask是什么嚷量?
AsyncTask就是異步處理的任務(wù),它是Handler加上線程池的封裝類逆趣,線程池可以維護(hù)數(shù)量,主要是可以避免不必要的創(chuàng)建和開銷嗜历,AsyncTask必須要在實(shí)例的主線程中創(chuàng)建宣渗,它的回調(diào)方法,Android也會(huì)自動(dòng)的去調(diào)用梨州,注意的是痕囱,一個(gè)AsyncTask的實(shí)例,只能調(diào)用一次的excute方法暴匠。
AsyncTask的基本使用
首先AsyncTask是一個(gè)抽象類鞍恢,用于被繼承,而且要指定3個(gè)泛型參數(shù)每窖,也可以3個(gè)都指定為空帮掉。
public class MyAsyncTask extends AsyncTask<Params,Progress,Result> {
@Override
protected Void doInBackground(Void... voids) {
return null;
}
}
//Parm:啟動(dòng)任務(wù)時(shí)輸入?yún)?shù)的類型
//Progress:后臺(tái)任務(wù)執(zhí)行中返回的進(jìn)度值
//Result:后臺(tái)執(zhí)行完成后返回結(jié)果的類型
構(gòu)建 AsyncTaskd子類的回調(diào)方法。
-
doInBackground()
:必須重寫窒典,異步執(zhí)行后臺(tái)線程將要完成的任務(wù)蟆炊。 -
onPreExecute()
:執(zhí)行后臺(tái)耗時(shí)操作前被調(diào)用,一般用來完成用戶一些初始化操作瀑志。 -
onPostExecute()
:當(dāng)doInBackground方法完成后涩搓,系統(tǒng)會(huì)自動(dòng)調(diào)用,并且會(huì)將doInBackground返回的值傳遞給該方法劈猪。 -
onProgressUpdate()
:在doInBackground方法調(diào)用publishProgress方法后昧甘,更新任務(wù)的執(zhí)行進(jìn)度后,就會(huì)觸發(fā)該方法战得。
代碼如下:
package com.ju.synctask;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.io.InputStream;
import java.net.URLConnection;
/**
* 項(xiàng)目名: SyncTask
* 包名 com.ju.synctask
* 文件名: ImageTest
* 創(chuàng)建日期:2019/4/1
* 描述:圖片加載測(cè)試類
*/
public class ImageTest extends AppCompatActivity {
private static final String URL = "https://bmob-cdn-23214.b0.upaiyun.com/2019/03/30/9b72512c409fc6bd806acb50a7e7c748.jpg";
private ImageView iv;
private ProgressBar bar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
iv = findViewById(R.id.iv);
bar = findViewById(R.id.pro);
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute(URL);
}
private class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... strings) {
//取出相應(yīng)的參數(shù)值
String url = strings[0];
Bitmap bitmap = null;
URLConnection connection;
InputStream is;
try {
connection = new URL(url).openConnection();
is = connection.getInputStream();//獲取輸入流
BufferedInputStream bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);//將輸入流解析成bitmap
bis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
//初始化
bar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//獲取doInBackground的返回值充边,最后進(jìn)行處理
iv.setImageBitmap(bitmap);
bar.setVisibility(View.GONE);
}
}
}
模擬進(jìn)度條測(cè)試
package com.ju.synctask;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ProgressBar;
public class PBActivity extends AppCompatActivity {
private ProgressBar bar;
PAsyncTask pAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pbactiviity);
bar = findViewById(R.id.progress);
pAsyncTask = new PAsyncTask();
pAsyncTask.execute();
}
private class PAsyncTask extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... voids) {
//通過for循環(huán)模擬進(jìn)度條進(jìn)度
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
bar.setProgress(values[0]);
}
}
}
但是你這樣做發(fā)現(xiàn)了一個(gè)問題,如果點(diǎn)擊返回的話然后再次進(jìn)入會(huì)發(fā)現(xiàn)進(jìn)度條不動(dòng)了贡避,這其實(shí)是因?yàn)樯弦淮蔚倪M(jìn)度條任務(wù)沒有完成痛黎,AsyncTask的任務(wù)要進(jìn)行排隊(duì),那要怎么解決了刮吧,很簡單湖饱,可以讓AsyncTask和Activity的生命周期保持一次。
在Activity的聲明周期添加上這個(gè)
@Override
protected void onPause() {
super.onPause();
if (pAsyncTask != null && pAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
pAsyncTask.cancel(true);
}
}
再一次跑起來杀捻,發(fā)現(xiàn)沒什么卵用啊井厌。其實(shí),我們通過調(diào)用cancel調(diào)用的時(shí)候,并沒有吧AsyncTask的線程給停止掉仅仆,我們只是給這個(gè)AsyncTask發(fā)送了一個(gè)cancel的請(qǐng)求器赞,標(biāo)記為cancel的狀態(tài)而已。并不是真正的取消線程執(zhí)行墓拜。我們需要在doInBackground()
和onProgressUpdate()
添加一個(gè)isCancelled()
判斷港柜,來進(jìn)行停止AsyncTask,這樣就可以停止掉了咳榜。
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (isCancelled()) {
return;
}
bar.setProgress(values[0]);
}
總結(jié)
AsyncTask的基本使用方法就到此為止了夏醉,需要注意的一點(diǎn)是AsyncTask必須要在UI線程也就是主線程中進(jìn)行創(chuàng)建,也必須在UI線程中調(diào)用excute方法涌韩,重寫的那四個(gè)方法是自動(dòng)調(diào)用的畔柔。每個(gè)AsyncTask只能被執(zhí)行一次,多次調(diào)用有可能會(huì)出現(xiàn)異常臣樱。也不能在doInBackground()
方法里面更新UI靶擦,一定要在onProgressUpdate里進(jìn)行更新才行。