问题描述
我想取消运行的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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!