AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
使用的优点:
简单,快捷
过程可控
使用的缺点:
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来
在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。
使用的优点:
l结构清晰,功能定义明确
对于多个后台任务时,简单,清晰
使用的缺点:
在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)
首先我们得要一个布局
<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.asus.mytest2.ProgressActivity">
<SeekBar
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/sk"
android:max="100"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始下载1"
android:id="@+id/btn1_progress"/>
LinearLayout>
详细的步骤我写在代码中了:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
start.setOnClickListener(this);
end.setOnClickListener(this);
}
/**
* Params 启动任务执行的输入参数,比如HTTP请求的URL。它是可变型参数。 Progress 后台任务执行的百分比 Result
* 后台执行任务最终返回的结果,比如String。 如果某个泛型参数不需要指定类型时,可将它的设置为了Void
*
* @author TED
*
*/
class MyTask extends AsyncTask {
/**
* 该方法将在执行实际的后台操作前被UI 线程调用。
* 可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以中实现。
*/
@Override
protected void onPreExecute() {
tv.setText("下载中。。。");
super.onPreExecute();
}
/**
* 该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作 可以调用 publishProgress方法来更新实时的任务进度
*/
@Override
protected String doInBackground(String... params) {
for(int i = 0; i<100; i++){
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(i);
}
return null;
}
/**
* 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI
* 线程, 并且在界面上展示给用户.
*
*/
@Override
protected void onPostExecute(String result) {
tv.setText("下载完成");
super.onPostExecute(result);
}
/**
* 在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
*/
@Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
tv.setText("下载中"+values[0]+"%");
super.onProgressUpdate(values);
}
/**
* 在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
*/
@Override
protected void onCancelled() {
tv.setText("下载失败");
super.onCancelled();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
myTask.execute("下载中");
break;
case R.id.end:
myTask.cancel(true);
break;
default:
break;
}
}
AsyncTask实现进度条主要还是在于要理解每一个方法需要干什么,那么AsyncTask是否能实现两根进度条互相不干扰的进行读条呢,答案当然是肯定的
先来一个布局:
<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.asus.mytest2.ProgressActivity">
<SeekBar
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/sk"
android:max="100"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始下载1"
android:id="@+id/btn1_progress"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/sk2"
android:max="100"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始下载2"
android:id="@+id/btn2_progress"/>
LinearLayout>
在这里,要实现多个线程,就要好好考虑方法体中可变长度的参数,居然是可变长度,那么自然可以传入多个参数,因此就能实现同时进行其它线程的操作
package com.example.asus.mytest2;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
public class ProgressActivity extends AppCompatActivity {
private SeekBar progressBar1,progressBar2;
private Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress);
progressBar1 = (SeekBar) findViewById(R.id.sk);
progressBar2 = (SeekBar) findViewById(R.id.sk2);
btn1 = (Button) findViewById(R.id.btn1_progress);
btn2 = (Button) findViewById(R.id.btn2_progress);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btn1.setText("下载中。。。");
btn1.setEnabled(false);
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,1);
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btn2.setText("下载中。。。");
btn2.setEnabled(false);
new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,2);
}
});
}
class MyTask extends AsyncTask {
@Override
protected Integer doInBackground(Integer... values) {
for (int i = 0; i <= 100; i+=5) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(i,values[0]);
}
return values[0];
}
@Override
protected void onProgressUpdate(Integer... values) {
switch (values[1]){
case 1:
progressBar1.setProgress(values[0]);
btn1.setText("下载中" + values[0] + "%");
break;
case 2:
progressBar2.setProgress(values[0]);
btn2.setText("下载中" + values[0] + "%");
break;
default:
break;
}
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Integer result) {
switch (result){
case 1:
btn1.setText("下载完成");
btn1.setEnabled(true);
break;
case 2:
btn2.setText("下载完成");
btn2.setEnabled(true);
break;
default:
break;
}
super.onPostExecute(result);
}
}
}
这里我们在publishProgress(i,values[0]);传入了两个参数,通过onProgressUpdate方法来判断需要进行的操作,在这里,如要要让程序知道那个是控制那个,我们则需要引入executeOnExecutor()方法,通过内部类来调用,这样就可以完成实现多个线程的实现且互不干扰