標籤:通過 graphics phi ide 獲得 情況 inpu man java.net
Android之AsyncTask
1.AsyncTask從引用的包(package android.os)可以看出,它是Android給我們提供的一個處理非同步任務的類.通過此類,可以實現非同步處理最後完成UI更新.
2.對於Android UI更新,只能在主線程進程更新,此原因已經在前面(Android的訊息機制Handler)介紹,所以剩下只能通過子線程或者非同步進行更新.對於子線程進行更新,前面已經介紹,此處只介紹非同步方法呼叫進行的更新.
3.對於為什麼用非同步更新,以及是否會降級ui效能,那麼可以肯定的說如果不用非同步處理一些耗時操作,建立立一個線程同樣也會消耗資源,同樣也會耗時.而且對於子線程必須做到和ui同步,即ui銷毀前要對線程進行處理,否則很容易出現null 指標或者ui已經結束子線程還在跑的情況.而對於非同步處理是不會出現此情況的.下面會針對說明.
4.AsyncTask介紹:
(1)public abstract class AsyncTask<Params, Progress, Result>
Params:起動任務即非同步處理的參數doInBackground(Params... params)
Progress:背景工作執行中返回進度值的類型,onProgressUpdate(Progress... values)
Result:背景工作執行完成後返回結果的類型,onPostExecute(Result result)
(2)一些方法說明:
onPreExecute:執行後台之前,需要的一些初始化,此方法隸屬主線程
doInBackground:非同步任務處理處,耗時操作在此方法完成,此方法的執行在子線程完成.
onPostExecute:當doInBackground方法完成後,系統自動調用此方法,且將doInBackground方法返回的值傳入此方法進行ui的更新,此方法隸屬主線程.
onProgressUpdate:在doInBackground方法中調用publishProgress方法更新任務執行進度後,將回調用此方法,通過此方法可以知道任務進展.
publishProgress:此方法是發布進度的時候使用,當非同步方法呼叫doInBackground調用此方法後,onProgressUpdate會被回調.
(3)publishProgress此方法的工作源碼可以說明非同步處理為什麼是安全的:
@WorkerThread protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } } private static Handler getMainHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(Looper.getMainLooper()); } return sHandler; } } private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]);//執行的這個方法就是當前AsyncTask自身的finish()這個方法。而這正是說明了在正常執行完背景工作執行緒的doInBackground()之後再在主線程中執行finish() break; } } }
整個過程可以說明在更新進度的時候,會上對象鎖(AsyncTask.class),在執行完非同步後再線上程中執行finish方法,那麼此時將不會有不介面銷毀的時候組件還在work的情況.
5.下面通過demo示範一個典型的非同步處理實力:載入圖片。
package com.example.testactivityb; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class MainActivity extends Activity { private ImageView imageView ; private TextView textView; private static String URL = "http://pic1.sc.chinaz.com/files/pic/pic9/201808/zzpic13515.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView) findViewById(R.id.image); textView = (TextView)findViewById(R.id.textView); textView.setText("hello world,after a moment,it will disapear"); Log.d(this.toString(), "onCreate main thread "); //通過調用execute方法開始處理非同步任務.相當於線程中的start方法. new MyAsyncTask().execute(URL); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } class MyAsyncTask extends AsyncTask<String,Void,Bitmap> { //onPreExecute:非同步處理前的操作,此方法依然在主線程中 @Override protected void onPreExecute() { super.onPreExecute(); Thread.dumpStack(); Log.d(this.toString(), "onPreExecute ..."); //此處將textView設定為可見,僅表示在此可以設定ui相關的操作 textView.setVisibility(View.VISIBLE); } //doInBackground:進行非同步任務處理,另開了線程. @Override protected Bitmap doInBackground(String... params) { Log.d(this.toString(), "doInBackground ..."); //擷取傳進來的參數 String url = params[0]; Bitmap bitmap = null; URLConnection connection ; InputStream inputStream ; try { connection = new URL(url).openConnection();//url對象用openconnection()開啟串連,獲得URLConnection類對象,再用URLConnection類對象的connect()方法進行串連 inputStream = connection.getInputStream();//an input stream that reads from this open connection //為了更清楚的看到載入圖片的等待操作,將子線程休眠下. Thread.sleep(4000); BufferedInputStream bis = new BufferedInputStream(inputStream); bitmap = BitmapFactory.decodeStream(bis);//通過decodeStream方法解析輸入資料流 inputStream.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bitmap; } //onPostExecute用於UI的更新.此方法的參數為doInBackground方法返回的值. @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); Log.d(this.toString(), "onPostExecute ..."); //對UI進行操作,此時Bitmap是doInBackground處理後的結果. textView.setVisibility(View.GONE); imageView.setImageBitmap(bitmap); } } }
執行過程如下:
08-16 10:38:04.102 8437 8437 D AccessibilityManager: getInstance() new sInstance = [email protected], context = [email protected], userId = 0 08-16 10:38:04.159 8437 8437 D [email protected]: onCreate main thread 08-16 10:38:04.161 8437 8437 D [email protected]: onPreExecute ... 08-16 10:38:04.166 8437 8450 D [email protected]: doInBackground ... 08-16 10:38:04.285 1475 1536 I ActivityManager: Displayed com.example.testactivityb/.MainActivity: +318ms 08-16 10:38:08.506 8437 8437 D [email protected]: onPostExecute ...
Android的AsyncTask