关闭

AsyncTask同步加载基础

标签: Android学习asynctask
188人阅读 评论(0) 收藏 举报
分类:

学习 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]);
        }
    }
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3198次
    • 积分:213
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:6篇
    • 译文:0篇
    • 评论:0条