1.什么是AsyncTask?
AsyncTask是Android提供的实现代码量少的异步类。与Handler一样为了处理异步消息,忽略了Looper,MessageQueue,Handler等复杂对象,可以更便捷的完成异步耗时操作。最重要的不同是无需自己再创建启动子线程,而是使用AsyncTask封装好的的子线程。简单的来说,AsyncTask就是一个Handler和线程池的封装。
2.如何使用AsyncTask?
1.新建内部类继承AsyncTask;
2.AsyncTask的是三种泛型参数;
3.重写doInBackground抽象方法;(必须,子线程相关内容在这个方法中,无法进行UI更新)
4.重写onpreExecute方法;(异步任务开始执行时,系统最先调用此方法,可以对控件进行初始化操作)
5.重写onProgressUpdate方法;
6.重写onPostExcute方法(当doInBackground执行完后系统调用此方法,此方法运行在主线程中可以进行UI的更新)
7.在需要的地方调用execute方法。
3.AsyncTask中方法之间参数的传递
使用AsyncTask需要重写里面的多个方法,而方法之间参数进行传递数值,现在然我们看看参数都是从哪传递的。
首先我们新建好一个内部类继承AsyncTask,随便写上参数。
class Newclass extends AsyncTask <Integer , Integer , String >
然后重写好每一个方法,我们会发现每个方法后面都对应这我们写上的参数类型
@Override
protected String doInBackground (Integer... integers) {
publishProgress(1 );
return null ;
}
@Override
protected void onPostExecute (String s) {
super .onPostExecute(s);
}
@Override
protected void onProgressUpdate (Integer... values) {
super .onProgressUpdate(values);
}
当我们在需要的地方使用wang.execute(num)时,num的值会穿递到doInBackground方法的参数integers中。
而doInBackground的return的值会传递到onPostExecute的参数。
并且在doInBackground我们还可以用 publishProgress(**)来传递值给onProgressUpdate的Values中;
4.使用AsyncTask完成简单的计时器
首先我们创建好Activity并且完成好它的xml布局文件
<LinearLayout
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:orientation ="horizontal" >
<TextView
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:text ="输入计时时间:"
android:textSize ="20sp" />
<EditText
android:id ="@+id/edtixt"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:hint ="请输入数字"
android:numeric ="integer"
/>
</LinearLayout >
<View
android:layout_width ="match_parent"
android:layout_height ="1dp"
android:background ="#000" />
<TextView
android:id ="@+id/text2"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:text ="准备计时"
android:textSize ="20sp"
android:gravity ="center" />
<Button
android:id ="@+id/btn2"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:textSize ="20sp"
android:layout_gravity ="center"
android:gravity ="center"
android:text ="开始计时" />
</LinearLayout >
在Activity中定义好控件,并且绑定好ID,设置按钮的监听事件。
private void blindId() {
editText = findViewById(R.id .edtixt )
textView2 = findViewById(R.id .text 2)
button2 = findViewById(R.id .btn 2)
button2.setOnClickListener (this)
}
创建内部类继承AsyncTask,并重写doInBackground,onPostExecute,onPreExecute;
首先在进行耗时工作前设置TextView为"开始计时:" + 用户输入的值
@Override
protected void onPreExecute () {
super .onPreExecute();
textView2.setText("开始计时:" + num1);
}
在重写的doInBackground中进行子线程的耗时工作,设置读秒操作,利用 publishProgress(i)方法传递给onProgressUpdate。
@Override
protected String doInBackground (Integer... Integer) {
for (int i = num1; i >= 0 ; i--)
try {
Thread.sleep(1000 );
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null ;
}
在重写的onProgressUpdate接收每秒传递的数字,来更新UI界面
@Override
protected void onProgressUpdate (Integer... values) {
super .onProgressUpdate(values);
textView2.setText("开始计时:" + values[0 ]);
}
当耗时工作完成后doInBackground将会return值到onPostExecute,可以在onPostExecute直接设置UI界面更新
@Override
protected void onPostExecute (String s) {
super .onPostExecute(s);
if (s == null ) {
textView2.setText("finlish" );
}
最后点击事件中使用AsyncTask,使用editText.getText().toString()获取用户输入的值并用Integer.parseInt转为int型,并将值传递给AsyncTask的方法。
switch (view.getId ()) {
case R.id .btn 2:
num = editText.getText ().toString ()
num1 = Integer.parseInt (num)
Wang wang = new Wang()
wang.execute (num1)
// Toast.makeText (AsyActivity.this , "num1" , Toast.LENGTH _SHORT).show ()
break
}
5.使用AsyncTask做进度条
我们创建好Activity并且完成好它的xml布局文件,用SeekBar或progressBar做进度条。
<TextView
android:id ="@+id/textwang"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text ="准备下载"
android:textSize="20sp" />
<SeekBar
android:id ="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id ="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text ="开始下载" />
在Activity中定义好控件,并且绑定好ID,设置按钮的监听事件。
private void blindId() {
textView = findViewById(R.id .textwang )
button = findViewById(R.id .btn )
mProgressBar = findViewById(R.id .progressBar )
button.setOnClickListener (this);
}
创建内部类继承AsyncTask,并重写doInBackground,onPostExecute,onPreExecute,onProgressUpdate;
首先在进行耗时工作前设置进度条为0,并且将进度条最大值设置为下载时间;TextView为正在下载,按钮无法点击;
@Override
protected void onPreExecute () {
super .onPreExecute();
textView.setText("正在下载" );
button.setText("正在下载" );
button.setEnabled(false );
mProgressBar.setProgress(0 );
mProgressBar.setMax(10 );
}
在重写的doInBackground中进行子线程的耗时工作,设置读秒操作,利用 publishProgress(i)方法传递给onProgressUpdate。
@Override
protected String doInBackground (Integer... Integer) {
for (int i = 0 ; i <= Integer[0 ]; i++)
try {
Thread.sleep(1000 );
publishProgress(i );
} catch (InterruptedException e) {
e.printStackTrace();
}
return null ;
}
在重写的onProgressUpdate接收每秒传递的数字,来更新进度条
@Override
protected void onProgressUpdate (Integer... values) {
super .onProgressUpdate(values);
mProgressBar.setProgress(values[0 ]);
}
当耗时工作完成后doInBackground将会return值到onPostExecute,可以在onPostExecute直接设置UI界面更新+
@Override
protected void onPostExecute (String s) {
super .onPostExecute(s);
if (s == null ) {
textView.setText("下载完成" );
button.setText("下载完成" );
button.setEnabled(true );
}
}
最后点击事件中使用AsyncTask,使用editText.getText().toString()获取用户输入的值并用Integer.parseInt转为int型,并将值传递给AsyncTask的方法。
case R.id.btn:
Newclass task = new Newclass () ;
task.execute(10 );
break ;
6.execute与executeOnExecutor区别
首先execute与executeOnExecutor最主要的区别就是execute以单线程队列方式或线程池队列方式运行,就是说要当多个下载进度条同时下载,第一条完成后,第二条才会开始下载。而executeOnExecutor允许多个任务在由AsyncTask管理的线程池中并行执行,可以最多5个任务同时进行下载。
7.Handler与AsyncTask那个感觉更好
首先两个都是用于处理异步消息的,个人感觉Handler更利于理解,但是需要自己建立线程发送消息和创建Handler来捕获消息。而AsyncTask刚接触的时候,理解起来需要一会,而且里面传值方面,需要自己在代码里一点点的观察理解,但是AsyncTask试用起来减少很多代码量,所以在理解后使用AsyncTask可以减少很多麻烦的地方。两种方法一种便于理解,一种便于使用,看个人喜好。