今天初次接触AsyncTask,写了一个简单的定时器,来看一下效果图
AsyncTask是Android提供的一个工具类,顾名思义为异步执行任务。主要用来处理后台耗时比较多的任务, 不需要子线程和Handler就可以完成一步操作和刷新UI界面。
AsyncTask是一个抽象类,使用时需要继承这个类,定义一个他的派生类并重写相关方法,然后调用execute()方法。要注意,在继承时,需要设定三个泛型的Params、Progress、Result类型,如Asynctask<Integer,Integer,Void>
AsyncTask类的声明如下:
public abstract class AsyncTask<Params,Progress,Result>
可以看到,AsyncTask是一个泛型类,它的三个类型参数的含义如下:
(1)Params:是指调用execute()方法时传入的参数类型和doInBackground()的参数类型
(2)Progress:是指更新进度时传入的参数类型,即publishProgress()和onProgressUpdate()的参数类型
(3)Result:后台任务的返回结果类型,是指doInBackground()的返回值类型
AsyncTask类主要为我们提供了如下方法
(1)onPreExecute():此方法会在后台任务执行前被调用,用于进行一些准备工作
(2)doInBackground(Params...Params):可以此方法中定义要执行的后台任务,在这个方法中可以调用 publishProgress()来更新任务进度(publishProgress内部会调用onProgressUpdate方法)
(3)onProgressUpdate(Progress...values):由publishProgress内部调用,表示任务进度更新
(4)onPostExecute(Result result):后台任务执行完毕后此方法会被调用,参数即为后台任务的返回结果
(5)onCancelled():此方法会在后台任务取消时被调用
需要注意的是,在以上的方法中,除了doInBackground方法有AsyncTask内部线程池执行外,其余方法均在主线程中执行
为了正确的使用AsyncTask类,必须遵守以下几条准则:
(1)AsyncTask的实例必须在UI线程中创建
(2)excute()方法必须在UI线程中调用
(3)不要手动调用onPreExecute()、doInBackground(Params...Params)、onProgressUpdate(Progress...values)、 onPostExecute(Result result)这几个方法,需要在UI线程中实例化 这个task来调用
(4)该实例只能被执行一次,否则多次调用将会出现异常
下面直接上代码
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class AsyncTaskDemoActivity extends AppCompatActivity {
private Button start;
private TextView getTime;
private EditText setTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_demo);
bindView();
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (setTime.getText().length()==0){
start.setEnabled(false);
}else {
start.setEnabled(true);
}
}
};
//对文本框设置监听,当为空时,按钮不可用
setTime.addTextChangedListener(textWatcher);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获得输入的文本框的值
int value = Integer.parseInt(String.valueOf(setTime.getText()));
if (value > 0){
new Chronograph().execute(value);
}else {
Toast.makeText(AsyncTaskDemoActivity.this,"请输入一个大于0的整数值",Toast.LENGTH_SHORT).show();
}
}
});
}
public void bindView(){
start = (Button) findViewById(R.id.start);
getTime = (TextView) findViewById(R.id.getTime);
setTime = (EditText) findViewById(R.id.setTime);
}
private class Chronograph extends AsyncTask<Integer,Integer,Void>{
//此方法会在后台任务执行前被调用,用于进行一些准备工作
@Override
protected void onPreExecute() {
super.onPreExecute();
//在计时开始前,先使按钮和EditText不可用
start.setEnabled(false);
setTime.setEnabled(false);
}
@Override
protected Void doInBackground(Integer... params) {
//计时
for (int i = 0;i <= params[0];i++){
for (int j = 0;j < 60;j++){
try {
//发布增量
publishProgress(i,j);
if (i == params[0]){
return null;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (isCancelled()){
return null;
}
return null;
}
//由publishProgrss内部调用,表示任务进度更新
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//更新UI界面
String str = null;
if ((Integer.parseInt(String.valueOf(values[0]))<10)){
str = "0"+values[0];
}else {
str = values[0]+"";
}
str = str +":";
if (Integer.parseInt(String.valueOf(values[1]))<10){
str = str+ "0"+values[1];
}else {
str = str + values[1]+"";
}
getTime.setText(str);
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//重新使按钮和EditText可用
start.setEnabled(true);
setTime.setEnabled(true);
getTime.setText("00:00");
setTime.setText("");
}
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.administrator.myapplication.AsyncTaskDemoActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="定时(分钟)"
android:textSize="30sp"
android:gravity="center" />
<EditText
android:id="@+id/setTime"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"/>
<TextView
android:id="@+id/getTime"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:textSize="60sp"
android:text="00:00"
android:textColor="@color/colorPrimaryDark"
android:layout_gravity="center_horizontal"
android:gravity="center"/>
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="开始"
android:enabled="false"/>
</LinearLayout>
参考文章:《新编Anroid应用开发从入门到精通》