Android的AsyncTask

                                                                                  Android之AsyncTask
1.AsyncTask从引用的包(package android.os)可以看出,它是Android给我们提供的一个处理异步任务的类.通过此类,可以实现异步处理最后完成UI更新.
2.对于Android UI更新,只能在主线程进程更新,此原因已经在前面(Android的消息机制Handler)介绍,所以剩下只能通过子线程或者异步进行更新.对于子线程进行更新,前面已经介绍,此处只介绍异步方法进行的更新.
3.对于为什么用异步更新,以及是否会降级ui性能,那么可以肯定的说如果不用异步处理一些耗时操作,新建立一个线程同样也会消耗资源,同样也会耗时.而且对于子线程必须做到和ui同步,即ui销毁前要对线程进行处理,否则很容易出现空指针或者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 = android.view.accessibility.AccessibilityManager@a9d45fb, context = com.example.testactivityb.MainActivity@b6b7618, userId = 0
 08-16 10:38:04.159  8437  8437 D com.example.testactivityb.MainActivity@b6b7618: onCreate main thread 
 08-16 10:38:04.161  8437  8437 D com.example.testactivityb.MainActivity$MyAsyncTask@7e9fcb7: onPreExecute ...
 08-16 10:38:04.166  8437  8450 D com.example.testactivityb.MainActivity$MyAsyncTask@7e9fcb7: 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 com.example.testactivityb.MainActivity$MyAsyncTask@7e9fcb7: onPostExecute ...

 

 

 

 

 

  

posted @ 2018-08-20 14:49  syyh2006  阅读(142)  评论(0编辑  收藏  举报