本文介绍了无法取消AsyncTaskLoader运行的AsyncTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想取消运行的AsyncTask(在AsyncTaskLoader),当用户点击Home键。下面是我创建至今:

I want to cancel running AsyncTask (in AsyncTaskLoader) when the user clicks the home button. Here is what I created so far:

package cz.davidliska.android.loaders;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.util.Log;

public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Date> {
    private static final String TAG = "loader";
    private Date date;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LoaderManager.enableDebugLogging(true);
        getSupportLoaderManager().initLoader(0, savedInstanceState, this);
    }

    private static class DateLoader extends AsyncTaskLoader<Date> {
        public static final String STATE_DATE_LOADER = "dateloader.state";
        private Date mDate;

        public DateLoader(Context context, Bundle savedInstanceState) {
            super(context);
            if (savedInstanceState != null) {
                long timeStamp = savedInstanceState.getLong(STATE_DATE_LOADER);
                if (timeStamp != 0L) mDate = new Date(timeStamp);
            }
        }

        @Override
        protected void onStartLoading() {
            Log.d(TAG, "Loader.onStartLoading()");
            if (mDate != null) {
                deliverResult(mDate);
            } else {
                forceLoad();
            }
        }

        @Override
        public void deliverResult(Date data) {
            super.deliverResult(data);
            Log.d(TAG, "Loader.deliverResult()");
            mDate = data;
        }

        @Override
        protected void onStopLoading() {
            super.onStopLoading();
            cancelLoad(); // try to cancel AsyncTask
            Log.d(TAG, "Loader.onStopLoading()");
        }


        @Override
        protected void onForceLoad() { // overridden in AsyncTaskLoader
            super.onForceLoad();
            Log.d(TAG, "Loader.onForceLoad()");
        }

        @Override
        protected void onReset() {
            super.onReset();
            mDate = null;
            Log.d(TAG, "Loader.onForceLoad()");
        }

        @Override
        public void onContentChanged() {
            super.onContentChanged();
            Log.d(TAG, "Loader.onContentChanged()");
        }

        @Override
        protected void onAbandon() {
            super.onAbandon();
            Log.d(TAG, "Loader.onContentChanged()");
        }

        @Override
        public Date loadInBackground() { // AsyncTaskLoader only
            Log.d(TAG, "Loader.loadInBackground()");
            try {
                // there will be some HttpClient.execute()
                while(true) {
                    Thread.sleep(100);
                    Log.d(TAG, "Loader.loadInBackground() still running");
                }

            } catch (InterruptedException e) {
                Log.d(TAG, "Loader.loadInBackground() interupted");
            }
            Log.d(TAG, "Loader.loadInBackground() finished");
            return new Date();
        }

        @Override
        public void onCanceled(Date data) { // AsyncTaskLoader only
            super.onCanceled(data);
            Log.d(TAG, "Loader.onCanceled()");
        }

        @Override
        protected Date onLoadInBackground() { // AsyncTaskLoader only
            Log.d(TAG, "Loader.onContentChanged()");
            return super.onLoadInBackground();
        }

        @Override
        public void abandon() {
            Log.d(TAG, "Loader.abandon()");
            super.abandon();
        }

        @Override
        public boolean cancelLoad() {
            Log.d(TAG, "Loader.cancelLoad()");
            return super.cancelLoad();
        }

        @Override
        public void forceLoad() {
            Log.d(TAG, "Loader.forceLoad()");
            super.forceLoad();
        }

        @Override
        public boolean isAbandoned() {
            Log.d(TAG, "Loader.isAbandoned()");
            return super.isAbandoned();
        }

        @Override
        public boolean isReset() {
            Log.d(TAG, "Loader.isReset()");
            return super.isReset();
        }

        @Override
        public boolean isStarted() {
            Log.d(TAG, "Loader.isStarted()");
            return super.isStarted();
        }

        @Override
        public void reset() {
            Log.d(TAG, "Loader.reset()");
            super.reset();
        }

        @Override
        public void stopLoading() {
            Log.d(TAG, "Loader.stopLoading()");
            super.stopLoading();
        }

        @Override
        public boolean takeContentChanged() {
            Log.d(TAG, "Loader.takeContentChanged()");
            return super.takeContentChanged();
        }

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (date != null)
            outState.putLong(DateLoader.STATE_DATE_LOADER, date.getTime());
    }

    public Loader<Date> onCreateLoader(int id, Bundle args) {
        Log.d(TAG, "LoaderCallback.onCreateLoader()");
        if (args != null) Log.d(TAG, "bundle: " + args.getLong(DateLoader.STATE_DATE_LOADER));
        return new DateLoader(this, args);
    }

    public void onLoadFinished(Loader<Date> loader, Date data) {
        Log.d(TAG, "LoaderCallback.onLoadFinished(): " + new SimpleDateFormat("dd/MM/yyyy").format(data));
        date = data;
    }

    public void onLoaderReset(Loader<Date> loader) {
        Log.d(TAG, "LoaderCallback.onLoaderReset()");
    }
}

因此​​,在onStopLoading()我打电话cancelLoad(),我认为应该取消当前的任务,但AsyncTask的在AsyncTaskLoader仍在运行(while循环loadInBackground()仍在进行中)。

So in onStopLoading() i am calling cancelLoad(), which i think should cancel current task, but AsyncTask in AsyncTaskLoader is still running (while loop in loadInBackground() is still in progress).

现在的问题是,也许在cancelLoad()方法中的java.android.support.v4.content.AsyncTaskLoader.java,其中mTask.cancel(布尔)被称为与论据假:

The problem is maybe in cancelLoad() method in "java.android.support.v4.content.AsyncTaskLoader.java", where mTask.cancel(boolean) is called with "false" in arguments:

public boolean cancelLoad() {
    ...
    boolean cancelled = mTask.cancel(false);

有没有可能取消在AsyncTaskLoader运行的AsyncTask?

Is there any chance to cancel running AsyncTask in AsyncTaskLoader?

推荐答案

如果你的意思是是否有任何机会,以取消android.content.AsyncTaskLoader运行的AsyncTask?答案是肯定的:你只需要添加一些在你的loadInBackground法取消点,并检查取消请求是否已经发出(isLoadInBackgroundCanceled()==真),那么要么返回或抛出一个OperationCanceledException)

If you mean "Is there any chance to cancel running AsyncTask in android.content.AsyncTaskLoader?" the answer is yes: you just need to add some "cancel points" in your loadInBackground method and check whether a cancellation request has been issued (isLoadInBackgroundCanceled() == true), then either return or throw an OperationCanceledException).

AsyncTaskLoader的支持库版本使用的是虽然似乎没有完全实现消除在这个时候(不是在该框架的飞行途中,至少,和粗略比较的和装载机的支持版本似乎的建议的该取消的也许的不能在所有支持的...)。

The support library version of AsyncTaskLoader you are using though doesn't seem to fully implement cancellation at this time (not in mid-flight at least, and a cursory comparison of the framework and of the support version of Loader seems to suggest that cancellation might not be supported at all...).

http://developer.android.com/reference/android/content/ Loader.html http://developer.android.com/reference/android/support /v4/content/Loader.html

有两种方法来缓解,我想起这个问题:

Two ways to alleviate the problem come to my mind:

  • 创建您的装载机的两种实现(一个使用的API级别11以上的框架,一个没有对旧设备的取消功能)
  • 创建一个android.support.v4.content.Loader子类,并处理每一个AsyncTask的,并取消请求自己

这篇关于无法取消AsyncTaskLoader运行的AsyncTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-21 19:50