停止 AsyncTask doInBackground 方法。

3
我已经在一个类中创建了一个AsyncTask,并从片段中调用该任务。问题是,如果片段被销毁,我想停止doInBackground方法。为此,我在包含AsyncTask的类中创建了一个方法,并在该方法中使用cancel(true)来取消Asynctask对象。当我从片段的onDestroy()中调用此方法时,后台进程仍在运行。请告诉我正确的方法来停止asynctask的doInBackground。
这是包含asynctask的类:
public class CarDetail implements Parcelable{

private String carId;
private String carName;
private String imageUrl;
private String thumbUrl;
private String dailyPrice;
private String weeklyPrice;
private String weekendPrice;
private String deposit;
private String minimumAge;
private String color;
private String make;
private String location;
private String bodyType;
private String fuelType;
private String transmission;
private String carType;
private String model;
private String description;
private Bitmap image;
private Bitmap thumbImage;
private CarListAdapter carAdapter;
private ImageLoadTask task = new ImageLoadTask();

public CarDetail() {
    super();
    // TODO Auto-generated constructor stub
}

public CarDetail(String carId, String carName, String imageUrl,
        String thumbUrl, String dailyPrice, String weeklyPrice,
        String weekendPrice, String deposit, String minimumAge,
        String color, String make, String location, String bodyType,
        String fuelType, String transmission, String carType, String model,
        String description) {
    super();
    this.carId = carId;
    this.carName = carName;
    this.imageUrl = imageUrl;
    this.thumbUrl = thumbUrl;
    this.dailyPrice = dailyPrice;
    this.weeklyPrice = weeklyPrice;
    this.weekendPrice = weekendPrice;
    this.deposit = deposit;
    this.minimumAge = minimumAge;
    this.color = color;
    this.make = make;
    this.location = location;
    this.bodyType = bodyType;
    this.fuelType = fuelType;
    this.transmission = transmission;
    this.carType = carType;
    this.model = model;
    this.description = description;

    // TO BE LOADED LATER - OR CAN SET TO A DEFAULT IMAGE
    this.image = null;
    this.thumbImage = null;
}

public String getCarId() {
    return carId;
}

public void setCarId(String carId) {
    this.carId = carId;
}

public String getCarName() {
    return carName;
}

public void setCarName(String carName) {
    this.carName = carName;
}

public String getImageUrl() {
    return imageUrl;
}

public void setImageUrl(String imageUrl) {
    this.imageUrl = imageUrl;
}

public String getThumbUrl() {
    return thumbUrl;
}

public void setThumbUrl(String thumbUrl) {
    this.thumbUrl = thumbUrl;
}

public String getDailyPrice() {
    return dailyPrice;
}

public void setDailyPrice(String dailyPrice) {
    this.dailyPrice = dailyPrice;
}

public String getWeeklyPrice() {
    return weeklyPrice;
}

public void setWeeklyPrice(String weeklyPrice) {
    this.weeklyPrice = weeklyPrice;
}

public String getWeekendPrice() {
    return weekendPrice;
}

public void setWeekendPrice(String weekendPrice) {
    this.weekendPrice = weekendPrice;
}

public String getDeposit() {
    return deposit;
}

public void setDeposit(String deposit) {
    this.deposit = deposit;
}

public String getMinimumAge() {
    return minimumAge;
}

public void setMinimumAge(String minimumAge) {
    this.minimumAge = minimumAge;
}

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public String getMake() {
    return make;
}

public void setMake(String make) {
    this.make = make;
}

public String getLocation() {
    return location;
}

public void setLocation(String location) {
    this.location = location;
}

public String getBodyType() {
    return bodyType;
}

public void setBodyType(String bodyType) {
    this.bodyType = bodyType;
}

public String getFuelType() {
    return fuelType;
}

public void setFuelType(String fuelType) {
    this.fuelType = fuelType;
}

public String getTransmission() {
    return transmission;
}

public void setTransmission(String transmission) {
    this.transmission = transmission;
}

public String getCarType() {
    return carType;
}

public void setCarType(String carType) {
    this.carType = carType;
}

public String getModel() {
    return model;
}

public void setModel(String model) {
    this.model = model;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public Bitmap getImage() {
    return image;
}

public void setImage(Bitmap image) {
    this.image = image;
}

public Bitmap getThumbImage() {
    return thumbImage;
}

public void setThumbImage(Bitmap thumbImage) {
    this.thumbImage = thumbImage;
}

 public void loadImage(CarListAdapter carAdapter) {
        // HOLD A REFERENCE TO THE ADAPTER
        this.carAdapter = carAdapter;
        if (thumbUrl != null && !thumbUrl.equals("")) {
            //new ImageLoadTask().execute(thumbUrl);

            task.execute(thumbUrl);
        }
 }

    // ASYNC TASK TO AVOID CHOKING UP UI THREAD
    private class ImageLoadTask extends AsyncTask<String, String, Bitmap> {

        @Override
        protected void onPreExecute() {
            Log.i("ImageLoadTask", "Loading image...");
        }

        // PARAM[0] IS IMG URL
        protected Bitmap doInBackground(String... param) {
            Log.i("ImageLoadTask", "Attempting to load image URL: " + param[0]);
            try {
                Bitmap b = JsonParser.downloadBitmap(param[0]);
                return b;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        protected void onProgressUpdate(String... progress) {
            // NO OP
        }

        protected void onPostExecute(Bitmap ret) {
            if (ret != null) {
                Log.i("ImageLoadTask", "Successfully loaded " + carName + " image");
                image = ret;
                if (carAdapter != null) {
                    // WHEN IMAGE IS LOADED NOTIFY THE ADAPTER
                    carAdapter.notifyDataSetChanged();
                }
            } else {
                Log.e("ImageLoadTask", "Failed to load " + carName + " image");
            }
        }
    }


    /* everything below here is for implementing Parcelable */

    // 99.9% of the time you can just ignore this
    public int describeContents() {
        return 0;
    }

    // write your object's data to the passed-in Parcel
    public void writeToParcel(Parcel out, int flags) {
        out.writeString(carId);
        out.writeString(carName);
        out.writeString(imageUrl);
        out.writeString(thumbUrl);
        out.writeString(dailyPrice);
        out.writeString(weeklyPrice);
        out.writeString(weekendPrice);
        out.writeString(deposit);
        out.writeString(minimumAge);
        out.writeString(color);
        out.writeString(make);
        out.writeString(location);
        out.writeString(bodyType);
        out.writeString(fuelType);
        out.writeString(transmission);
        out.writeString(carType);
        out.writeString(model);
        out.writeString(description);

    }

    // this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
    public static final Parcelable.Creator<CarDetail> CREATOR = new Parcelable.Creator<CarDetail>() {
        public CarDetail createFromParcel(Parcel in) {
            return new CarDetail(in);
        }

        public CarDetail[] newArray(int size) {
            return new CarDetail[size];
        }
    };

    // example constructor that takes a Parcel and gives you an object populated with it's values
    private CarDetail(Parcel in) {
        carId = in.readString();
        carName = in.readString();
        imageUrl = in.readString();
        thumbUrl = in.readString();
        dailyPrice = in.readString();
        weeklyPrice = in.readString();
        weekendPrice = in.readString();
        deposit = in.readString();
        minimumAge = in.readString();
        color = in.readString();
        make = in.readString();
        location  = in.readString();
        bodyType = in.readString();
        fuelType = in.readString();
        transmission = in.readString();
        carType = in.readString();
        model = in.readString();
        description = in.readString();

    }



 public void stopImageLoadTask(){
    task.cancel(true);
    Log.d("stop", "stop");
}

这是一个片段。
 public class ServiceCarListFragment extends Fragment {

private String url;
private ArrayList<CarDetail> carDetailList = new ArrayList<CarDetail>();
private CarListAdapter adapter;
private ListView mList ;
private ProgressDialog progressDialog;
OnCarListItemSelectedListener mCallback;
private boolean connectionStatus;

// Container Activity must implement this interface
public interface OnCarListItemSelectedListener {
    public void onCarSelected(CarDetail car);
}

@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        mCallback = (OnCarListItemSelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnCarListItemSelectedListener");
    }
}





@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    Log.d("Services", "On Create");
    url = getActivity().getIntent().getStringExtra("url");
    adapter = new CarListAdapter(getActivity() , carDetailList);

    ConnectionHandler conn = new ConnectionHandler();
    connectionStatus = conn.connectionStatus(getActivity());

    if(connectionStatus){

        new DownloadCarDetail().execute(url);
    }

    else{
        DialogFragment newFragment = new DialogHandler(getActivity());
        newFragment.show(getFragmentManager(), "internet");
    }


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    Log.d("Services", "On CreateView");
    View v = inflater.inflate(R.layout.fragment_service_car_list, container,false);
    mList = (ListView)v.findViewById(R.id.list);
    mList.setAdapter(adapter);  
    mList.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View selectedView, int position,
                long id) {
            // TODO Auto-generated method stub
            CarDetail car = (CarDetail)adapter.getItem(position);
            mCallback.onCarSelected(car);
        }
    });
    return v;
}

class DownloadCarDetail extends AsyncTask<String, String, ArrayList<CarDetail>>{



    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        progressDialog = ProgressDialog.show(getActivity(), null, "Loading...",true);

    }

    @Override
    protected ArrayList<CarDetail> doInBackground(String... params) {
        // TODO Auto-generated method stub
        ArrayList<CarDetail> carDetailList = JsonParser.parseJson(params[0]);
        return carDetailList;
    }

    @Override
    protected void onPostExecute(ArrayList<CarDetail> carDetailList) {
        // TODO Auto-generated method stub
        //adapter = new CarListAdapter(getActivity(),ServiceCarListFragment.this.carDetailList);
        //mList.setAdapter(adapter);
        progressDialog.dismiss();
        ServiceCarListFragment.this.carDetailList.addAll(carDetailList);
        adapter.notifyDataSetChanged();
        for (CarDetail car : carDetailList) {
            // START LOADING IMAGES FOR EACH CAR
            car.loadImage(adapter);

    }
        carDetailList.clear();
        Log.d("ewgf", String.valueOf(carDetailList.size()));
 }

}



@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    new CarDetail().stopImageLoadTask();
}

}
1个回答

5

public final boolean cancel (boolean mayInterruptIfRunning)

尝试取消此任务的执行。如果该任务已经完成、已被取消或由于其他原因无法取消,则此尝试将失败。如果成功,且在调用cancel时此任务尚未启动,则此任务不应运行。如果任务已经启动,则mayInterruptIfRunning参数确定是否应中断执行此任务的线程以尝试停止任务。

使用isCancelled()

public final boolean isCancelled ()

如果此任务在正常完成之前被取消,则返回true。如果您正在对任务调用cancel(boolean),则应从doInBackground(Object [])定期检查此方法返回的值,以尽快结束任务

Android - 强制取消AsyncTask

请参阅上面链接中的被接受的答案和commonsware的答案。


如果我执行异步任务10次,并像上面所做的那样取消它,这是否意味着其中一个被取消,其余九次运行? - Ravi
引用文档中的内容:“从DONUT开始,这被改为线程池,允许多个任务并行操作。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。”因此,我认为10个异步任务不会并行运行。请查看链接http://developer.android.com/reference/android/os/AsyncTask.html。 - Raghunandan
任务只能执行一次(如果尝试进行第二次执行,将抛出异常)。请查看上面评论中发布的链接中的线程规则主题。 - Raghunandan
谢谢,我明白了。你能提供一个好的链接,教我如何正确地使用isCancelled()来处理这种情况吗? - Ravi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接