Android AsyncTask分析

---恢复内容开始---

因为android的UI线程是不安全的,如果你UI线程里执行一些耗时任务,很容易就导致程序崩溃。并且目前网络任务也不能够在UI线程里执行。处理这些问题除了直接写一个线程以外,Android还提供一个AsyncTask(异步任务类)来更简单的处理一些耗时任务。

AsyncTask<>是一个抽象类,通常用于继承,继承时需要指定三个泛型参数。

1、Params:启动任务时传入的参数的类型。这是一个数组,可以传多个参数。调用时使用params[0]、params[1]、params[2]来获取。

2、Progress:后台任务完成的进度值的类型。

3、Result:后台任务执行完毕返回结果的类型。

使用AsyncTask需要如下三步:

1、继承抽象类,实现一个子类,传入三个泛型参数。如果有参数不需要使用可设为Void。

2、根据需要,可实现以下方法。

  • doInBackground(Params...):该方法是必须的,这个方法下写的是后台线程要执行的任务,并且会在子线程运行(其他方法都是在UI线程执行)。。该方法可以调用publicProgress(Progress...values)方法更新任务的进度。
  • onProgressUpdate(Progress... values):该方法在上一步调用publicProgress时触发。
  • onPreExecute():该方法会在执行doInBackground方法前执行,用于做一些准备工作。
  • onPostExecute(Result result):当doInBackground执行结束之后,系统会自动调用该方法,返回值也会传到此函数。我们可以在这里完成后台线程执行后的结果。

3、最后用新建我们继承类后的结果,然后调用execute(Params... params)。

  注意:对象必须在UI线程中创建、execute方法必须在UI线程中调用、以上四个方法都需系统自动调用、每个对象只能被执行一次,多次调用引发异常。

实例

讲了那么多铺垫,让我们来讲个例子吧~

我现在想从互联网上下载一张图片,就使用这个AsyncTask来做一下吧~

为让所有方法都实现一次,我们用两种方法实现:1、下载完毕后直接进行显示。2、一边加载一边显示进度,加载完毕显示图片。

下面是第一种的代码,相对简单一点,只用了两个函数。

public class MainActivity extends Activity {

    int downloadSize;
    int fileSize;

    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);

        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }

    class MyOnClickListener implements android.view.View.OnClickListener{

        @Override
        public void onClick(View v) {

            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }
    }

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

        @Override
        protected Bitmap doInBackground(String... params) {

            String imageUrl = params[0];

            URL url;
            try {
                url = new URL(imageUrl);
                InputStream is = url.openStream();
                BitmapFactory.Options op = new BitmapFactory.Options();
                op.inSampleSize = 2;
                Bitmap bitmap = BitmapFactory.decodeStream(is, null,
                        op);

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);

            iv.setImageBitmap(result);
        }
  }
}

上面的代码的功能是点击按钮,然后doInBackground后台下载图片,下载完毕onPostExecute显示图片。仅仅使用了两个函数,但是实现了AsyncTask的核心功能。

然后让我们感受一下能够显示进度的。

public class MainActivity extends Activity {

    int downloadSize;
    int fileSize;

    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);
        progressBar = (ProgressBar) findViewById(R.id.bar);

        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }

    Handler handler = new Handler(){

        public void handleMessage(android.os.Message msg)
        {

        }
    };

    class MyOnClickListener implements android.view.View.OnClickListener{

        @Override
        public void onClick(View v) {

            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }
    }

    class AsyncDownload extends AsyncTask<String, Integer, Void>
    {

        @Override
        protected Void doInBackground(String... params) {

            String imageUrl = params[0];

            try {
                URL url = new URL(imageUrl);
                URLConnection conn = url.openConnection();
                conn.connect();
                InputStream is = conn.getInputStream();
                fileSize = conn.getContentLength(); 

                publishProgress(0x111);

                FileOutputStream fos = new FileOutputStream(getPath());
                byte[] bytes = new byte[1024];
                int len = -1;
                while((len = is.read(bytes))!=-1)
                {
                    fos.write(bytes, 0, len);
                    downloadSize+=len;
                    publishProgress(0x222);
                }
                publishProgress(0x333);
                is.close();
                fos.close();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);

            switch(values[0])
            {
            case 0x111:
                progressBar.setMax(fileSize);
                break;
            case 0x222:
                progressBar.setProgress(downloadSize);
                break;
            case 0x333:
                try {
                    if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){
                        FileInputStream fis = new FileInputStream(getPath());
                        iv.setImageBitmap(BitmapFactory.decodeStream(fis));
                    }
                    downloadSize = 0;
                    fileSize = 0;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }

    public String getPath() {
        File root = getExternalCacheDir();
        if (root != null)
        {
            return root.getAbsolutePath()  + "test.jpg";
        }

        return null;
    }
}

这里实现的功能是点击下载按钮,后台从互联网加载文件,首先获取文件大小,设置progressbar最大值,然后一边下载、一边存入本地、一边设置progressbar的值,实现进度条。下载完毕从本地获取图片显示出来。这一次多使用了显示进度的函数onProgressUpdate。

其实,onProgressUpdate这个函数一般我们在线程里会用Handler来实现。

在AsyncTask给我们把平常使用线程进行异步操作的所用东西打包在一起了,不得不说确实省了一些事。

实际上能够用AsyncTask实现的东西完全可以直接用线程来实现~

我在些第二个代码的时候写顺了手,用Handler实现了一遍,大家在下面可以看一下。

public class MainActivity extends Activity {

    int downloadSize;
    int fileSize;

    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);
        progressBar = (ProgressBar) findViewById(R.id.bar);

        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }

    Handler handler = new Handler(){

        public void handleMessage(android.os.Message msg)
        {
            switch(msg.what)
            {
            case 0x111:
                progressBar.setMax(fileSize);
                break;
            case 0x222:
                progressBar.setProgress(downloadSize);
                break;
            case 0x333:
                try {
                    if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){
                        FileInputStream fis = new FileInputStream(getPath());
                        iv.setImageBitmap(BitmapFactory.decodeStream(fis));
                    }
                    downloadSize = 0;
                    fileSize = 0;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    };

    class MyOnClickListener implements android.view.View.OnClickListener{

        @Override
        public void onClick(View v) {

            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }
    }

    class AsyncDownload extends AsyncTask<String, Integer, Void>
    {

        @Override
        protected Void doInBackground(String... params) {

            String imageUrl = params[0];

            try {
                URL url = new URL(imageUrl);
                URLConnection conn = url.openConnection();
                conn.connect();
                InputStream is = conn.getInputStream();
                fileSize = conn.getContentLength(); 

                handler.sendEmptyMessage(0x111);

                FileOutputStream fos = new FileOutputStream(getPath());
                byte[] bytes = new byte[1024];
                int len = -1;
                while((len = is.read(bytes))!=-1)
                {
                    fos.write(bytes, 0, len);
                    downloadSize+=len;
                    handler.sendEmptyMessage(0x222);
                }
                handler.sendEmptyMessage(0x333);
                is.close();
                fos.close();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    }

    public String getPath() {
        File root = getExternalCacheDir();
        if (root != null)
        {
            return root.getAbsolutePath()  + "test.jpg";
        }

        return null;
    }
}

啦啦啦,就到这里吧~

时间: 2024-10-16 10:38:36

Android AsyncTask分析的相关文章

Android AsyncTask 分析内部实现

转载自:http://blog.csdn.net/jjwwmlp456/article/details/38623563 sdk3.0前,使用内部的线程池,多线程并发执行.线程池大小等于5,最大达128 sdk3.0后,使用默认的serial线程池,执行完一个线程,再顺序执行下一个线程.sdk3.0<=current version <= sdk4.3时 线程池大小等于5,最大达128 sdk4.4后线程池大小等于 cpu count + 1,最大值为cpu count * 2 + 1 sdk

Android多线程分析之五:使用AsyncTask异步下载图像

Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<Android多线程分析之中的一个:使用Thread异步下载图像>中.曾演示了怎样使用 Thread 来完毕异步任务. Android 为了简化在 UI 线程中完毕异步任务(毕竟 UI 线程是 app 最重要的线程).实现了一个名为 AysncTask 的模板类.使用 AysncTask 能够在异步任务进行的同

源码分析Android AsyncTask

Android UI操作是线程不安全的,若想在子线程红进行UI操作,需要借助Android提供的Handler.Android提供的AsyncTask其实是对Handler的封装,方便我们在子线程中更新UI元素.AsyncTask是一个泛型类,书写格式为: AsyncTask<Params, Progress, Result>.这三个参数的用途如下: 1. Params 这三个参数的用途如下: 1. Params 在执行AsyncTask时需要传入的参数,可用于在后台任务中使用. 2. Pro

Android多线程分析之四:MessageQueue的实现

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前面两篇文章<Android多线程分析之二:Thread的实现>,<Android多线程分析之三:Handler,Looper的实现>中分别介绍了 Thread 的创建,运行,销毁的过程以及 Thread与 Handler,Looper 之间的关联:Thread 在其 run() 方法中创建和运行消息处理循环 Looper,而 Looper::loop() 方法不断地从 Messag

[学习总结]7、Android AsyncTask完全解析,带你从源码的角度彻底理解

我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制.之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考 Android Handler.Message完全解析,带你从源码的角度彻底理解 . 不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活方便地从子线程切换到UI线程,我们本篇文章的主角也就正是它了. Asyn

AsyncTask分析

AsyncTask分析 经典版异步任务 public abstract class MyAsyncTask { private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { onPostExecute(); }; }; /** * 后台任务执行之前 提示用户的界面操作. */ public abstract void onPreExecute(); /** * 后台任务执行

Android多线程分析之三:Handler,Looper的实现

Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前文<Android多线程分析之二:Thread的实现>中已经具体分析了Android Thread 是怎样创建,执行以及销毁的,其重点是对对应 native 方法进行分析,今天我将聚焦于 Android Framework 层多线程相关的类:Handler, Looper, MessageQueue, Message 以及它们与

Android架构分析之Android消息处理机制(三)

作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:4.4.2 本文我们来分析AndroidUI线程即主线程是怎样实现对消息的处理的. UI线程的实现类定义在frameworks/base/core/java/android/app/ActivityThread.java文件中.我们来看Android对ActivityThread类的说明 : 130/** 131 * This manages the execution of the main

android Asynctask的优缺点?能否同时并发100+asynctask呢?

一  Asynctask的优缺点? AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 优点: 1.简单,快捷 2.过程可控 3.使用的缺点: 缺点: 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来. Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理. 首先明确Android之所以有Handle