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>泛型1,> |
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 |
(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的几个方法的返回值与参数类型还得自己继续的研究研究啊。。有点蒙。。