详解AsyncTask的cancel的有效用法,强制停止AsyncTask异步任务

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。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值