异步任务加载网络数据——AsyncTask使用

AsyncTask类简单介绍

  • Android从1.5开始引入了AsyncTask这个类,AsyncTask内部使用Java 1.5的并发库比普通初级Android开发者编写的Thread+Handler稳定很多
  • AsyncTask封装了Thread和Handler,使我们用起来更加方便,不用去关注Handler。由于后台线程不能更新UI,而很多情况下,我们在后台线程做完一件事后,一般都会更新UI,一般我们会这样做:在UI线程创建一个handler对象,在后台线程中发送一条message,再在Handler中去处理这个message,进而更新UI。
  • 用了AsyncTask后,我们就不用再去关注Handler了。它定义了三种泛型,分别是Params、Progress和Result,分别表示请求的参数、任务的进度和获得的结果数据。

一、使用AsyncTask的好处
  1. 底部封装了线程池技术,其中的方法很容易调用。
  2. 直接调用相关方法,进行UI界面的更新。
  3. 一旦任务多,就不用每次都new新的线程,可以直接使用。

二、执行顺序
onPreExecute()【执行前开启】 ---> doInBackground() ---> onProgressUpdate() ---> onPostExecute()

三、实现原理:
1.线程池的创建:
    在创建了AsyncTask的时候,会默认创建一个线程池ThreadPoolExecutor,并默认创建出5个线程放入到线程池中,最多可防128个线程;且这个线程池是公共的唯一一份。

2.任务的执行:
    在execute中,会执行run方法,当执行完run方法后,会调用scheduleNext()不断的从双端队列中轮询,获取下一个任务并继续放到一个子线程中执行,直到异步任务执行完毕。

3.消息的处理:
    在执行完onPreExecute()方法之后,执行了doInBackground()方法,然后就不断的发送请求获取数据;在这个AsyncTask中维护了一个InternalHandler的类,这个类是继承Handler的,获取的数据是通过handler进行处理和发送的。在其handleMessage方法中,将消息传递给onProgressUpdate()进行进度的更新,也就可以将结果发送到主线程中,进行界面的更新了。

四、AsyncTask工作原理详解
  1. onPreExecute(): 在UI线程里面调用,它在这个task执行后会立即调用。我们在这个方法里面通常是用于建立一个任务,比如显示一个等待对话框来通知用户。

  2. doInBackground(Params…):这个方法从名字就可以看出,它是运行在后台线程的,在这个方法里面,去做耗时的事情,比如下载访问网络,操作文件等。在这个方法里面,我们可以调用publishProgress(Progress…)来调用当前任务的进度,调用了这个方法后,对应的onProgressUpdate(Progress…)方法会被调用,这个方法是运行在UI线程的。

  3. onProgressUpdate(Progress…):运行在UI线程,在调用publishProgress()方法之后。这个方法用来在UI上显示任何形式的进度,比如你可以显示一个等待对话框,也可以显示一个文本形式的log,还可以显示toast对话框。

  4. onPostExecute(Result):当task结束后调用,它运行在UI线程。

  5. 取消一个task,我们可以在任何时候调用cancel(Boolean)来取消一个任务,当调用了cancel()方法后,onCancelled(Object)方法就会被调用,onPostExecute(Object)方法不会被调用,在doInBackground(Object[])方法中,我们可以用isCancelled()方法来检查任务是否取消。

小主意:
  • AsyncTask实例必须在UI线程中创建
  • execute(Params…)方法必须在UI线程中调用。
  • 不用手动调用onPreExecute() doInBackground() onProgressUpdate() onPostExecute()方法。
  • 一个任务只能被执行一次。

示例代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView    
       android:layout_width="fill_parent"   
       android:layout_height="wrap_content"   
       android:text="Hello , Welcome to Andy's Blog!"/>  
    <Button  
       android:id="@+id/download"  
       android:layout_width="fill_parent"  
       android:layout_height="wrap_content"  
       android:text="Download"/>  
    <TextView    
       android:id="@+id/tv"  
       android:layout_width="fill_parent"   
       android:layout_height="wrap_content"   
       android:text="当前进度显示"/>  
    <ProgressBar  
       android:id="@+id/pb"  
       android:layout_width="fill_parent"  
       android:layout_height="wrap_content"  
       style="?android:attr/progressBarStyleHorizontal"/>  
</LinearLayout>
package sn.demo;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

public class DownloadTask extends AsyncTask<Integer, Integer, String> {
    //后面尖括号内分别是参数(线程休息时间),进度(publishProgress用到),返回值 类型  

    private Context mContext=null;
    private ProgressBar mProgressBar=null;
    private TextView mTextView=null;
    public DownloadTask(Context context,ProgressBar pb,TextView tv){
        this.mContext=context;
        this.mProgressBar=pb;
        this.mTextView=tv;
    }
    /*
     * 第一个执行的方法
     * 执行时机:在执行实际的后台操作前,被UI 线程调用
     * 作用:可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
     * @see android.os.AsyncTask#onPreExecute()
     */
    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        Log.d("sn", "00000");
        super.onPreExecute();
    }

    /*
     * 执行时机:在onPreExecute 方法执行后马上执行,该方法运行在后台线程中
     * 作用:主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected String doInBackground(Integer... params) {
        // TODO Auto-generated method stub
        Log.d("sn", "1111111");
        for(int i=0;i<=100;i++){
            mProgressBar.setProgress(i);
            publishProgress(i);
            try {
                Thread.sleep(params[0]);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return "执行完毕";
    }

    /*
     * 执行时机:这个函数在doInBackground调用publishProgress时被调用后,UI 线程将调用这个方法.虽然此方法只有一个参数,但此参数是一个数组,可以用values[i]来调用
     * 作用:在界面上展示任务的进展情况,例如通过一个进度条进行展示。此实例中,该方法会被执行100次
     * @see android.os.AsyncTask#onProgressUpdate(Progress[])
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        // TODO Auto-generated method stub
        Log.d("sn", "2222222222");
        mTextView.setText(values[0]+"%");
        super.onProgressUpdate(values);
    }

    /*
     * 执行时机:在doInBackground 执行完成后,将被UI 线程调用
     * 作用:后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户
     * result:上面doInBackground执行后的返回值,所以这里是"执行完毕"  
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        Log.d("sn", "3333333333");

        super.onPostExecute(result);
    }
}
package sn.demo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class AsyncTaskDemoActivity extends Activity {
    /** Called when the activity is first created. */
    private Button download;
    private TextView tv;
    private ProgressBar pb;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initView();
    }
    private void initView() {
        // TODO Auto-generated method stub
        tv=(TextView)findViewById(R.id.tv);
        pb=(ProgressBar)findViewById(R.id.pb);
        download=(Button)findViewById(R.id.download);
        download.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                DownloadTask dt=new DownloadTask(AsyncTaskDemoActivity.this,pb,tv);
                dt.execute(100);
            }
        });
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值