AsyncTask同步加载基础

原创 2015年11月19日 15:24:51

学习 http://www.imooc.com/learn/377 笔记

异步任务:
由于Android单线程模型,只有主线程即UI线程可以对UI进行操作,然而一些耗时任务必须放在非主线程中进行。

AsyncTask是一个Android封装好的组件用于进行异步任务处理。

用处:在子线程中更新UI,封装简化异步操作

一个典型的AsyncTask使用

public class MyAsyncTask extends AsyncTask<Void,Void,Void> {


    /**第二执行,执行真正的后台耗时操作
     * @param params
     * @return
     */
    @Override
    protected Void doInBackground(Void... params) {
        Log.d("Tony","doInBackground");
        return null;
    }

    /**
     * 首先执行,完成准备工作
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.d("Tony", "onPreExecute");
    }

    /**
     * 第三执行,用于展示处理的结果
     * @param aVoid
     */
    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        Log.d("Tony", "onPostExecute");
    }

    /**
     * 单独调用才能执行
     * @param values
     */
    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
        Log.d("Tony", "onProgressUpdate");
    }
}

具体介绍:

AsyncTask<Params, Progress, Result>

是一个抽象类,通常用于被继承,继承AsyncTask需要指定如下三个泛型参数:
Params:启动任务时输入参数的类型,比如HTTP请求的URL
Progress:后台任务执行中返回进度值的类型
Result:后台执行任务完成后返回结果的类型,比如String,Integer等
不一定非要使用参数,不使用时设为Void类型

doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定
AsyncTask<  doInBackground接受的参数 , 显示进度的参数  ,  doInBackground返回和onPostExecute传入的参数  >


AsyncTask的回调方法
onPreExecute():
前置调用,完成初始化任务,运行在主线程,可操作UI,比如显示进度条或者控件实例化
onPostExecute()
后置操作,承接doInBackground,运行在主线程,可操作UI,将结果传递给UI
doInBackground():
核心部分,必须重写,异步处理需要耗时的工作
onProgressUpdate():
进度条更新,如果doInBackground()调用了publishProgress()更新任务进度就会调用


运行顺序是onPreExecute->doInBackground->onPostExecute
onProgressUpdate()在加载进度条时被调用进行


Async注意事项
1:Async实例需要在:UI线程中创建
2:必须在UI线程中调用AsyncTask的execute()方法,这个方法是运行相应AsyncTAsk
3:重写的方法由系统自动调用
4:每个AsyncTask方法只能调用一次




AsyncTask异步加载网络图片实例:


main.xml  设置加载网络图片和进度条的按钮

<span style="font-size:10px;"><strong> </strong><Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Button"
        android:text="Image Test"
        android:onClick="loadImage"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ProgressBtn"
        android:text="Progress Test"
        android:onClick="loadProgress"/></span>

mainactivity 主要代码不多,用于响应按钮

 public void loadImage(View view){
     startActivity(new Intent(this, ImageTest.class));
    }
    public void loadProgress(View view){
        startActivity(new Intent(this,ProgressBarTest.class));
    }

image.xml 显示网络图片的UI界面

<ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <ProgressBar
        android:id="@+id/progressbar"
        android:visibility="gone"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
ImageTest 实现网络加载的主线程,按下MainActivity的按钮后会跳转到这个线程,内部类ImageAsyncTask实现异步加载
public class ImageTest extends Activity {

    private ImageView mImageView;
    private ProgressBar mProgressBar;
    private static String URL=
            "http://img.my.csdn.net/uploads/201504/12/1428806103_9476.png";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image);
        mImageView= (ImageView) findViewById(R.id.image);
        mProgressBar=(ProgressBar)findViewById(R.id.progressbar);
        //开启异步线程操作,设置传递进去的操作
        new ImageAsyncTask().execute(URL);

    }
    class ImageAsyncTask extends AsyncTask<String,Void,Bitmap>{

        //进行顺序:onPreExecute->doInBackground->onPostExecute

        /**
         * 前置操作,显示进度条,操作UI
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgressBar.setVisibility(View.VISIBLE);
        }

        /**
         * 后置操作,承接doInBackground,操作UI
         * @param bitmap
         */
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            mProgressBar.setVisibility(View.INVISIBLE);
            mImageView.setImageBitmap(bitmap);
        }

        /**
         * 真正的异步操作,以下都在子线程中进行。之前两个方法都在主线程中进行
         * @param params
         * @return
         */
        //String... param是可变长数组
        @Override
        protected Bitmap doInBackground(String... params) {
            //获取传递进来的url参数,因为只有一个所以在数组的0位
            String url=params[0];
            Bitmap bitmap=null;
            URLConnection urlConnection;
            InputStream inputStream;

            try {
                //异步操作图片加载和解析
                // URl->InputStream->BufferedInputStream->Bitmap
                urlConnection=new URL(url).openConnection();
                inputStream=urlConnection.getInputStream();
                BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
                //将输入流解析成Bitmap图片
                bitmap= BitmapFactory.decodeStream(bufferedInputStream);
                //关闭输入流
                inputStream.close();
                bufferedInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }


            //返回给onPostExecute()
            return bitmap;

        }
    }
}


AsyncTask异步加载进度条实例:

progressBarTest 用于AsyncTask模拟进度条

因为在进度条运行时按返回键挂起,重新执行一个新的进度条ProgressAsyncTask时,必须等之前的ProgressAsyncTask执行完毕后才可以执行,导致界面出现进度条不运行的现象,所以实现了AsyncTask的关闭

public class ProgressBarTest extends Activity {

    private ProgressBar mprogressBar;
    private ProgressAsyncTask mTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progressbar);
        mprogressBar=(ProgressBar)findViewById(R.id.pB);
        mTask=new ProgressAsyncTask();
        mTask.execute();

    }

    //目的是在AsyncTask挂起后结束线程,因为如果在进度条运行时按返回键挂起,重新执行一个新的
    //进度条ProgressAsyncTask时,必须等之前的ProgressAsyncTask执行完毕后才可以执行,导致界面
    //出现进度条不运行的现象,所以希望一旦ProgressAsyncTask挂起立刻结束线程
    @Override
    protected void onPause() {
        super.onPause();
       //如果当前进度条进程mTask不为空且正在异步加载
        if (mTask!=null&&mTask.getStatus()==AsyncTask.Status.RUNNING){

            //cancel()只是将对应的AsyncTask即mTask标记为cancel状态,
            // 并不是真正的取消线程的执行,Java中没办法直接停止一个线程
            //解决方法是在ProgressAsyncTask中加入判断cancel标记语句if(isCancelled())
            mTask.cancel(true);
        }
    }

    class ProgressAsyncTask extends AsyncTask<Void,Integer,Void>{

        @Override
        protected Void doInBackground(Void... params) {
            //模拟进度栏的更新
            for (int i=0;i<100;i++){
                if(isCancelled()){
                    break;
                }
                publishProgress(i);
                //让线程睡眠300毫秒,延缓更新速度
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (isCancelled()){
                return;
            }
            //得到进度更新值
            mprogressBar.setProgress(values[0]);
        }
    }
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

【Android基础】AsyncTask示例——加载网络图片

网络操作是一个严重的耗时操作,所以从Android 4.0版本开始,网络操作就被严禁放在主线程中,所以网络操作只能放在异步任务中。下面是一个从网络上下载图片的示例,示例分为两个部分: - 异步处理下...

AsyncTask异步线程实现加载网络图片

  • 2015年08月09日 21:20
  • 1.47MB
  • 下载

android基础---AsyncTask, 后台执行任务并同步更新前端UI

AsyncTask为我们提供了一个在后台执行耗时的操作并同步更新UI的方法. AsyncTask中有三个参数:       class MyAsyncTask extends AsyncTas...
  • BHduke
  • BHduke
  • 2013年10月10日 16:57
  • 1379

AsyncTask异步加载

  • 2016年06月04日 00:02
  • 2.74MB
  • 下载

Asynctask异步加载的使用

  • 2016年07月23日 12:51
  • 1.46MB
  • 下载

利用同步线程类AsyncTask 显示 下载的进度条进度变化

import java.util.ArrayList; import android.os.AsyncTask; import android.os.Bundle; import android.a...

Android 应用开发 之通过AsyncTask与ThreadPool(线程池)两种方式异步加载大量数据的分析与对比

在加载大量数据的时候,经常会用到异步加载,所谓异步加载,就是把耗时的工作放到子线程里执行,当数据加载完毕的时候再到主线程进行UI刷新。在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一是...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AsyncTask同步加载基础
举报原因:
原因补充:

(最多只允许输入30个字)