Android多线程之AsyncTask

AsyncTask是一种轻量级的异步任务类,不需要借助线程Handler就可以实现,它是在线程池中执行任务,然后把执行的进度和返回结果传递给主线程,在主线程中更新UI

AsyncTask是一个抽象类,定义了3个泛型参数:

  • Param:启动任务时需要传入的参数类型
  • Progress:后台任务完成进度的参数类型
  • Result:任务执行完毕后返回的结果类型

使用AsyncTask的方法如下:

1、定义AsyncTask的子类,指定3个泛型参数类型,如果某个泛型参数不需要指定类型,可以指定为Void

2、重写AsyncTask的方法:

  • doPreExecute():在执行后台任务前调用,通常用于一些准备工作,如显示一个进度条
  • doInBackground():后台线程将要执行的任务,在此方法中可以调用publishProgress(Progress… values)方法更新进度
  • onProgressUpdate(Progress… values):调用publicProgress()方法后会触发该方法
  • onPostExecute():当doInBackground()方法完成后会调用该方法,并将doInBackground()方法的返回值传给该方法

3、调用AsyncTask的execute()方法启动任务

下面使用AsyncTask加载一张网络图片

页面布局有一个Button和一个ImageView,点击Button后开始加载图片,用一个进度条显示进度,加载完成后显示在ImageView中

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.testasynctask.MainActivity" >

    <Button
        android:id="@+id/loadPicture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="加载图片" />

    <ImageView 
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

MainActivity.java

public class MainActivity extends ActionBarActivity {

    Button loadPicture;
    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadPicture = (Button)findViewById(R.id.loadPicture);
        imageView = (ImageView)findViewById(R.id.image);
        loadPicture.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                LoadTask loadTask = new LoadTask(MainActivity.this);
                loadTask.execute("http://pic.qiantucdn.com/58pic/12/57/33/90y58PICcWt.jpg!/fw/780/watermark/url/L3dhdGVybWFyay12MS4zLnBuZw==/align/center");
            }
        });
    }

    class LoadTask extends AsyncTask<String, Integer, Bitmap> {

        Context context;
        ProgressDialog dialog;
        long fileSize; //下载的文件大小

        public LoadTask(Context context) {
            this.context = context;
        }

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            dialog = new ProgressDialog(context);
            dialog.setTitle("任务执行中");
            dialog.setMessage("正在加载图片...");
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setMax(100);
            dialog.setIndeterminate(false);
            dialog.show();
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // TODO Auto-generated method stub
            try {
                URL url = new URL(params[0]);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                fileSize = connection.getContentLength();
                File file = new File("sdcard/image.png");
                RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
                randomAccessFile.setLength(fileSize);
                InputStream inputStream = connection.getInputStream();
                int readSum = 0;
                int hasRead;
                byte[] bytes = new byte[1024];
                while((hasRead = inputStream.read(bytes)) != -1) {
                    randomAccessFile.write(bytes, 0, hasRead);
                    readSum += hasRead;
                    publishProgress((int)(readSum / fileSize));
                }
                randomAccessFile.close();
                Bitmap bitmap = BitmapFactory.decodeFile("sdcard/image.png");
                return bitmap;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            dialog.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            // TODO Auto-generated method stub
            dialog.dismiss();
            imageView.setImageBitmap(result);
        }
    }
}

点击按钮后开始启动AsyncTask开始下载图片,在开始前先显示了一个下载进度对话框,下载后,先将图片保存在手机存储中,下载完成后将图片作为Bitmap返回,在onPostExecute方法中关闭进度框,然后显示图片

运行程序

这里写图片描述

加载了一张Batman的海报

使用AsyncTask时有几点需要注意:

1、必须在UI线程中创建AsyncTask
2、必须在UI线程中调用execute()方法
3、不可以直接调用doInBackground()、onPreExecute()、onProgressUpdate()、onPostExecute()方法
4、每个AsyncTask只能执行一次

另外一点,从Android3.0开始,AsyncTask采用一个线程来串行执行任务,可以通过AsyncTask的executeOnExecutor()方法来并行执行任务

新建LoadTask

class LoadTask extends AsyncTask<Void, Void, Void> {

        String taskName;

        public LoadTask(String name) {
            taskName = name;
        }

        @Override
        protected Void doInBackground(Void... params) {
            // TODO Auto-generated method stub
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i(TAG, "Task " + taskName + " executed");
            return null;
        }

    }

在doInBackground里等待了3秒,然后打印了一句log,在Activity里新建3个Task实例并启动任务

loadPicture.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                LoadTask task1 = new LoadTask("Task1");
                LoadTask task2 = new LoadTask("Task2");
                LoadTask task3 = new LoadTask("Task3");
                task1.execute();
                task2.execute();
                task3.execute();
            }
        });

运行程序,点击按钮开始任务

这里写图片描述

每个任务执行耗时3秒,3个任务是依次执行的

使用executeOnExecutor()方法来执行任务

loadPicture.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                LoadTask task1 = new LoadTask("Task1");
                LoadTask task2 = new LoadTask("Task2");
                LoadTask task3 = new LoadTask("Task3");
                task1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                task2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                task3.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
        });

运行结果

这里写图片描述

3个任务执行时间是相同的,这也证明任务是并行执行的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值