AsynTask是Handler的轻量级形式,他可以用作专门的处理耗时操作。有时我们会发现,在主线程睡眠的时候,你执行别的操作的时候会出现“卡屏”状态,这样的效果极为不好。但是我们可以通过AsynTask去解决这个问题。

“卡屏”现象

   (1)创建自定义类对象 模拟耗时操作  

public class Mythread {//自定义类    public static void sleepy(){        try {            Thread.sleep(5000);//模拟耗时操作        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

   (2)在主线程中单击start按钮时调用,单击print按钮时输出hello到控制台

public class MainActivity extends Activity implements OnClickListener{    private Button startBtn,printbtn;//声明按钮    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //查找资源                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    startBtn = (Button) findViewById(R.id.start);        printbtn  =(Button) findViewById(R.id.printBtn);        //为按钮添加监听        startBtn.setOnClickListener(this);        printbtn.setOnClickListener(this);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                }    @Override    public void onClick(View arg0) {        switch (arg0.getId()) {        case R.id.start:            //自定义线程类睡眠方法的调用            Mythread.sleepy();//这样使用的话会出现卡屏的状态            break;        case R.id.printBtn:            System.out.println("hello");            break;        }    }}

(3)结果:

若直接单击print方法没问题,后台输出正常

◆但若先单击start按钮,在单击任意次数的print按钮,都不会马上看见效果,而是等待睡眠5秒之后一并输出。

   如何解决“卡屏”现象?先来看看AsynTast吧。

   一:原理

    其实启动AsynTask,就相当于又开辟了一个线程,在这个线程中专门处理耗时操作,从而不会耽误用户主UI的其他操作,提高用户体验。

   二:创建及常用方法

   1:创建

   继承自AsynTask类,但有三个泛型,这里要注意一下,泛型用的全是包装类。

class MyAsynTask extends AsyncTask
<泛型1, 泛型2, 泛型3>

   2:常用方法及参数

(1)泛型3 doInBackground(泛型1):核心的处理耗时工作。方法的返回值类型:泛型3;参数类型:泛型1。参数的值来自于主界面启动AsynTask时传递的值。

   (2)onPostExecute(泛型3):异步结束时执行的方法。参数的值来自于doInBackground的返回值,因此参数的类型为:泛型3.

   (3)onPreExecute():在异步开始时就会执行的方法,也就是会在doInBackground方法执行之前执行。

   (4)onProgressUpdate(泛型2):与主线程UI的交互。参数类型:泛型2。参数的值来源于在doInBackground方法中通过publishProgress传递过来的值。

   三:如何解决“卡屏现象”?

   (1)创建继承自AsynTask的类,重写其中的doInBackground方法

   (2)在doInBackground方法中调用耗时操作

public class MyAsynTask extends AsyncTask
{ @Override protected String doInVoid... params) { Mythread.sleepy();//专门处理耗时 的操作 return null; }}

   (3)在主线程start按钮的监听中,不再是直接调用耗时操作,而是创建AsynTask对象,通过execute启动线程

case R.id.start:                                                                                                                                                                                                                                                                                                                                                                                                  //MyAsynTask myAsynTask = new MyAsynTask();            //myAsynTask.execute();//启动AsynTask,这样就不会出现卡屏的状态了            break;

   (4)结果:这是无论怎样单击,什么顺序单击均不会出现“卡屏”现象。

    四:AsynTask的应用

   实现的功能:仍然是上一篇博文中进度条与TextView控件的同步使用。

   (1)创建类继承自AsynTask,注意泛型类型的添加

   (2)提供成员属性(主界面上要同步的控件),添加构造方法

private TextView tv;//成员变量    private ProgressBar bar;//成员变量    public MyAsynTask(TextView tv, ProgressBar bar) {        super();        this.tv = tv;        this.bar = bar;    }

   (3)重写onPreExecute()方法:让他给出提示“异步开始了”

// 在异步开始时就会执行的方法,也就是会在doInBackground方法执行之前执行    @Override    protected void onPreExecute() {        tv.setText("异步开始了");        super.onPreExecute();    }

   (4)重写doInBackground()方法:完成值的更新

/**     *  核心处理方法,它的参数有主界面的启动时传递进来     *  返回类型:泛型3     *  参数类型:泛型1     */    @Override    protected String doInString...  params) {        int count = 0;//初始化变量        for (count = 0; count <= 100; count++) {            try {                Thread.sleep(100);//每个一秒count加1            } catch (InterruptedException e) {                e.printStackTrace();            }            // 传给了onProgressUpdate方法            publishProgress(count);//这个count将会传给onProgressUpdate中参数        }        return count+"";//返回值给onPostExecute方法,以便于结束的判断    }

   (5)重写onPostExecute()方法:结束时给出提示信息

// 异步结束时执行的方法,参数来自于doInBackground的返回值,也就是这里的vcount;@Overrideprotected void onPostExecute(String result) {    if (result != null) {        tv.setText("异步结束了,当前的I值为:" + result+"");    }    super.onPostExecute(result);}

   (6)重写onProgressUpdate()方法:更新主UI

// 与主线程UI的交互,参数来自于doInBackground方法中的publishProgress的参数值@Overrideprotected void onProgressUpdate(Integer... values) {    bar.setProgress(values[0]);//更新主Ui中的进度条    tv.setText(values[0] + "");//更新主UI中的文本框    super.onProgressUpdate(values);}

   (7)主UI中为按钮添加监听,启动AsynTask

btn.setOnClickListener(new OnClickListener() {                                                            @Override            public void onClick(View v) {                //实例化AsynTask对象            MyAsynTask myAsynTask = new MyAsynTask(tv, bar);            //启动AsynTask            myAsynTask.execute();                                                                }

   (8)结果

   其中AsynTask的几个方法的返回值与参数类型还得自己继续的研究研究啊。。有点蒙。。