AsyncTask - 非同步任務


AsyncTask是一個相當好用的類別,是專門用來處理背景任務與更新UI的class。

Android 4.0 之後,網路溝通行為都不能在主執行緒(Main Thread)執行,

主執行緒又稱UI執行緒(UI Thread),任何有關UI的東西都在主執行緒中執行,若是你的程式佔據主執行緒很久,使用者體驗會非常的差,

5秒沒有反應的話也會造成程式崩潰,也就是ANR(Application Not Responding)問題,也就是應用程式沒有回應。

Log.d("onClick = " , String.valueOf(Thread.currentThread().getId()));使用這個可以印出行續的編號,若為1則為主執行續,也就是能夠更新ui的執行續。
一般要做複雜的計算並且更新UI的時候,通程會使用Thread搭配Handler一起使用

例如這樣:
private Handler handler = new Handler();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler.postDelayed(yourRunnable, 100);
}
private Runnable yourRunnable = new Runnable() {
public void run() {
//something
handler.postDelayed(this, 100);
}
};

不更新ui的時候可以直接使用創建thread:
private void NewThread(){
new Thread(new Runnable() {
@Override
public void run() {
//...
}
}).start();
}

需要更新ui的時候可以使用runOnUiThread,或是將runOnUiThread塞進其他thread裡面:
private void yourFunction(){
runOnUiThread(new Runnable() {
@Override
public void run() {
//something
}
});
}

建立新的執行續會使用大量資源,

若是在處理一個必須頻繁的更新UI並且不斷的建立新執行續的一個任務,例如:相簿畫廊下載圖片等等,為了要方便管理我們的任務,我們可以使用AsyncTask這個class來管理thread創建的任務。


AsyncTask有四個主要步驟
private class AsyncTask 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);
}
}


若是我們需要利用AsyncTask創建的執行續建立新的view,例如下載一張圖後就新增一個ImageView並把它顯示出來的話,可以利用這樣的方式:


private class AsyncTask extends AsyncTask<String , Integer , Bitmap>{
private Context mContext;
private LinearLayout linearLayout;
Bitmap bit;
public void setView(LinearLayout ll,Context c){
linearLayout = ll;
mContext = c;
}
@Override
protected Bitmap doInBackground(String... params) {
//執行中 在背景做事情
for (String urlStr : params) {
try {
System.out.println(urlStr);
InputStream img_stream;
URL img_url = new URL(urlStr);
img_stream = img_url.openStream();
bit = BitmapFactory.decodeStream(img_stream);
} catch (Exception e) {
e.printStackTrace();
}
publishProgress();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
//執行中 可以在這邊告知使用者進度
super.onProgressUpdate(values);
ImageView iv = new ImageView(mContext);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv.setImageBitmap(bit);
linearLayout.addView(iv);
}
}
關鍵在於使用在MainActivity把Content傳入AsyncTask這個class讓他知道新的view要建立在哪裡。



簡單下載json資料範例

public class TransTask extends AsyncTask<String,Void,String>{
private StringBuilder sb;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... strings) {
URL url = null;
try {
url = new URL(strings[0]);
InputStream is = url.openStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
sb = new StringBuilder();
String line =in.readLine();
while (line!=null){
sb.append(line);
line = in.readLine();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d(TAG, "onPostExecute: "+s);
}
}
view raw AsyncTask.java hosted with ❤ by GitHub

留言

這個網誌中的熱門文章

android service作法

android app之間使用socket做溝通

html css & bootstrap心得