此文,仅做为个人学习Android,记录成长以及方便复习!
通过AsyncTask模拟下载进度,以及通过cancel进行状态标记,那么可以在AsyncTask中监测这样的改变,一旦当前状态改为cancelled,我们就要跳出循环,立刻结束当前操作,从而结束整个线程逻辑。
首先是一个按钮的布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/bt1"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载"/>
</LinearLayout>
在Activity实例化按钮并添加监听事件
MainActivity.java
package com.rui.pgasynctask;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.Button;
/**
* Created by qqazl001 on 2018/3/29.
*/
public class MainActivity2 extends Activity{
private Button bt;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button)findViewById(R.id.bt1);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//跳转下载Activity
Intent intent = new Intent(MainActivity.this,MainActivity.class);
startActivity(intent);
}
});
}
}
添加一个布局文件,存放一个ProgressBar和TextView,显示进度和数值
activity2_main.xml
ProgressBar中设置为水平方向显示进度条 style="?android:attr/progressBarStyleHorizontal"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:max="100"
/>
<TextView
android:id="@+id/tv1"
android:layout_below="@+id/pb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"/>
</RelativeLayout>
接下里了就是重头戏了
MainActivity.java
package com.rui.pgasynctask;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
//声明ProgressDialog,TextView,MyAsyncTask
private ProgressBar pb;
private TextView tv1;
private MyAsyncTask mtask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//实例化pd和tv1
pb = (ProgressBar)findViewById(R.id.pb);
tv1 = (TextView)findViewById(R.id.tv1);
//实例化内部类MyAsyncTask
mtask = new MyAsyncTask();
//启动异步加载
mtask.execute();
}
//当Activity失去焦点的时候
@Override
protected void onPause() {
//判断MyAsyncTask不为空,且状态是运行状态
if(mtask!=null && mtask.getStatus() == AsyncTask.Status.RUNNING ){
//AsyncTask标记为cancel状态,并不是真正地取消线程的执行。
mtask.cancel(true);
}
super.onPause();
}
//创建一个异步加载内部类,继承AsyncTask
public class MyAsyncTask extends AsyncTask<Void,Integer,Void>{
//实现doInBackground方法
@Override
protected Void doInBackground(Void... voids) {
//循环产生下载的效果
for(int i=0;i<=100;i++){
//判断是否被标记为true
if(isCancelled()){
//被标记则中断循环
break;
}
//调用周期的下一个方法,传值进度
publishProgress(i);
//睡眠50毫秒,模拟下载
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
//展示进度
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//判断是否被标记,如果被标记则终止
if(isCancelled()){
return;
}
//进度赋值给Pd
pb.setProgress(values[0]);
//tv1显示进度
tv1.setText("正在下载:"+values[0]+"%");
}
}
}
不等进度条满就后退再执行,会发现后面执行的进度条迟迟没有响应,为什么呢?这并非bug,而是 AsyncTask 所实行的一种机制。AsyncTask的底层是通过线程池去作用的。当一个线程没有完成的时候,后面的线程就无法开始。我们上一节课用了for()循环去执行进度条 的更新操作,必须等到for()循环结束后才会执行下一个Task。
令AsyncTask的生命周期和Activity或者Fragment的生命周期保持一致就可以了。
那要如何快速停止线程呢?
1. 在onPause()中标记取消状态:mTask.cancel(true);既然我们已经标记了cancel状态,那么可以在AsyncTask中监测这样的改变,一旦当前状态改为cancelled,我们就要跳出循环,立刻结束当前操作,从而结束整个线程逻辑。
2. 在doInBackground()方法的for()循环内添加isCancelled()对线程的状态进行判断:if(isCancelled())break;
3. 同理,在onProgressUpdate()方法中也做类似的处理:if(isCancelled())return;通过如上操作,我们就能快速停止当前线程,将处理权交给下一个AsyncTask。