AsyncTask是最常用的异步任务,随便一搜都知道如何使用。我在开发过程中也经常用到。很多刚入行的开发者,包括我自己都会遇到一个问题,AsyncTask异步任务,该如何停止,有个cancel,但cancel以后,根本没停下来,这是因为excuse()执行的异步任务是不会停止的,一直到任务执行结束。这意味着cancel就没什么实际作用了。
所以,这个时候,考验java基础能力的时候到了,我在开发中就有这么一个案例,扫描文件,扫到一半,用户觉得不爽,不扫了,要停止。
上面都说过了,要想让AsyncTask异步任务停止,只能让它执行完毕。思路很明显,既然我们不能强制使它停止,只有更快地使它执行完毕。
return这个大家都懂的java关键字,跳过本方法return后面的代码,我介绍的这个案例就充分利用了return让我的AsyncTask异步任务以最快的速度执行完毕,达到跟强制停止一样的效果。
贴代码:
MainActivity.java
package com.ljy.testasync;
import java.io.File;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends Activity {
@Bind(R.id.progress)
SeekBar progress;
@Bind(R.id.btn_switch)
Button btn;
private ScanFile task;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setData();
}
private void setData() {
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(btn.getText().toString().equals("开始")){
start();
}else{
if(task!=null&&!task.isCancelled()){
task.cancel(true);
task=null;
reset();
}
}
}
});
reset();
}
private void reset() {
progress.setProgress(0);
btn.setText("开始");
}
private void start(){
btn.setText("停止");
task=new ScanFile();
task.execute();
}
private class ScanFile extends AsyncTask<String, Integer, String>{
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
progress.setProgress(values[0]);
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
btn.setText("开始");
}
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
ScanFileMethod(null);
return null;
}
}
private void ScanFileMethod(String path){
/*
* 这里是第一处,方法开始的时候,包括【第一次开始】和【递归的时候】会调用到。
*
* 如果task已经cancel了,
* 而excuse()开始的task是一定得执行完才会结束的,
* 可通过return让task尽早结束,
* 这样就不影响下次重新开始扫描。
*/
if(task.isCancelled())
return;
File root;
File[] root_list;
if(path==null){
root=new File(Environment.getExternalStorageDirectory().toString());
}
else{
root=new File(path);
}
root_list=root.listFiles();
if(root_list!=null&&root_list.length>0){
File child;
for(int i=0;i<root_list.length;i++){
/*
* 这里是第二处,进入到文件目录的列表循环的时候。
*
* 如果task已经cancel了,
* 而excuse()开始的task是一定得执行完才会结束的,
* 可通过return让task尽早结束,
* 这样就不影响下次重新开始扫描。
*/
if(task.isCancelled())
return;
child=root_list[i];
if(child.isDirectory()){
ScanFileMethod(child.getAbsolutePath());
System.out.println("---->folder");
}else{
System.out.println("---->file");
}
if(path==null)
task.onProgressUpdate((int)(i*100.0/root_list.length));
}
}else{
System.out.println("---->null");
}
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SeekBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"/>
<Button
android:id="@+id/btn_switch"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="开始"
android:textSize="20dp"/>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ljy.testasync"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<application android:allowbackup=""true"/>
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity"
android:label=""@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN />
<category android:name="android.intent.category.LAUNCHER />
</intent-filter>
<pre name="code" class="html"> </application>
</mainfest>
demo源码地址(免费下载):http://download.csdn.net/detail/qq_29623203/9489725。