关于Android AsyncTask的一些总结

来源:互联网 发布:分级基金套利软件 编辑:程序博客网 时间:2024/06/14 08:20

  根据Google自己的说法,AsyncTask只适用于数量不多且短暂的操作,至于原因嘛,可能是因为从Android 3.2开始,AsyncTask又被改成串行的了,这样如果你用AsyncTask执行很多任务,或者某个任务执行时间很长的话,那么后面的任务就没法及时执行了。下面先看它的一个典型用法,然后再具体展开说:

package com.whereru.testcode3;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.os.Bundle;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.widget.ImageView;import android.widget.ProgressBar;import java.io.IOException;import java.io.InputStream;import java.lang.ref.WeakReference;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    private ImageView mImageView;    private ProgressBar mProgressBar;    private DownloadTask mDownloadTask;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        System.out.println("MainActivity onCreate");        mImageView = (ImageView) findViewById(R.id.image_view);        mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);        URL[] urls = null;        try {            urls = new URL[]{                    new URL("http://img4.imgtn.bdimg.com/it/u=2317499888,864114656&fm=21&gp=0.jpg"),                    new URL("http://img0.imgtn.bdimg.com/it/u=4256573763,278547175&fm=21&gp=0.jpg"),                    new URL("http://img2.imgtn.bdimg.com/it/u=546811603,943746655&fm=21&gp=0.jpg"),                    new URL("http://img0.imgtn.bdimg.com/it/u=93040804,2971684664&fm=21&gp=0.jpg")            };        } catch (MalformedURLException e) {            e.printStackTrace();        }        mDownloadTask = new DownloadTask(this);        mDownloadTask.execute(urls);    }    @Override    protected void onDestroy() {        super.onDestroy();        mDownloadTask.cancel(false);        System.out.println("MainActivity onDestroy");    }    private static class DownloadTask extends AsyncTask<URL, Integer, List<Bitmap>> {        private WeakReference<MainActivity> mMainActivityWeakReference;        DownloadTask(MainActivity mainActivity) {            mMainActivityWeakReference = new WeakReference<>(mainActivity);        }        @Override        protected List<Bitmap> doInBackground(URL... urls) {            //工作线程,负责下载图片,并转化成Bitmap            HttpURLConnection httpURLConnection = null;            List<Bitmap> bitmapList = new ArrayList<>();            for (int i = 0; i < urls.length; i++) {                System.out.println("正在下载图片:" + (i + 1));                try {                    httpURLConnection = (HttpURLConnection)                            urls[i].openConnection();                    InputStream inputStream = httpURLConnection.getInputStream();                    if (httpURLConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {                        throw new IOException(httpURLConnection.getResponseMessage() + ":with" +                                urls[i]);                    }                    bitmapList.add(BitmapFactory.decodeStream(inputStream));                } catch (IOException e) {                    e.printStackTrace();                } finally {                    if (httpURLConnection != null) {                        httpURLConnection.disconnect();                    }                }                if (isCancelled()) {                    break;                }                publishProgress((int) (((float) (i + 1) / urls.length) * 100));            }            return bitmapList;        }        @Override        protected void onProgressUpdate(Integer... progress) {            System.out.println("更新进度条");            if (mMainActivityWeakReference.get() != null) {                mMainActivityWeakReference.get().mProgressBar.setProgress(progress[0]);//更新进度条            }        }        @Override        protected void onPostExecute(final List<Bitmap> bitmapList) {            System.out.println("图片下载完成,开始显示图片");            //图片下载完成后,在UI线程中每隔两秒显示一张图片            for (int i = 0; i < bitmapList.size(); i++) {                final int finalI = i;                new Handler().postDelayed(new Runnable() {                    @Override                    public void run() {                        if (mMainActivityWeakReference.get() != null) {                            mMainActivityWeakReference.get().mImageView                                    .setImageBitmap(bitmapList.get(finalI));                        }                    }                }, 2000 * i);                if (isCancelled()) {                    break;                }            }        }    }}

  布局文件:   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:layout_width="match_parent"              android:layout_height="match_parent"              android:orientation="vertical">    <ProgressBar        android:id="@+id/progress_bar"        style="@android:style/Widget.ProgressBar.Horizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"/>    <ImageView        android:id="@+id/image_view"        android:layout_width="300dp"        android:layout_height="300dp"/></LinearLayout>

  上面代码实现的功能就是从网上下载了4张图片,然后有个进度条可以显示下载进度,下载完成后,每隔两秒钟显示一张图片。
  下面说下一些注意问题。

0.

  如果你觉得Activity被销毁后就不需要相应AsyncTask接着执行任务了,记得在onDestroy中执行cancel方法。

1.  

  不管在你下载图片还是显示图片的for循环中记得用下:  

if (isCancelled()) {    break;}  

  这样可以确保在你取消相应任务的时候,可以及时停止接着做无用功。

2.

  使用静态内部类和弱引用避免可能发生的内存泄露。(其实我觉得吧,其实如果内存不是很紧张,问题也不是很大,AsyncTask执行完了,自然Activity也就可以被回收了,而AsyncTask本来就不是用来执行长时间任务的,正常使用也不会长时间占着内存,个人看法。。。)

3.

  考虑个问题,我们跳到了另一个Acyivity,然后我们并没有取消原来Activity的AsyncTask,而原来的Activity又被销毁了,会怎么样?
  如果内存泄露的问题没解决,那程序肯定不会奔溃。那么采用了上面的方法解决了内存泄露,程序就一定会奔溃?其实也不一定,主要看那个被销毁的Activity是不是被GC回收了。不过为了安全起见,我们上面都做了WeakReference.get() != null的判断。
  
  相关阅读:
  Android多线程任务优化1:探讨AsyncTask的缺陷
  

0 0