2012-07-23 75 views
1

我想在用户单击主页按钮时取消正在运行的AsyncTask(在AsyncTaskLoader中)。以下是我创建至今:无法取消AsyncTaskLoader中正在运行的AsyncTask

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仍在运行(而在loadInBackground循环()是仍在进行中)。

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

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

有没有机会取消在AsyncTaskLoader中运行AsyncTask?

+0

try boolean cancelled = mTask.cancel(true); – rajpara 2012-07-23 12:34:38

+0

不幸的是,mTask在AsyncTaskLoader中不可见 – 2012-07-23 13:15:39

回答

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



     @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"); 

        if(cancelled)     <--------- 
         return new Date();   <---------- 
       } 

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

这将适用于while循环,但不适用于长时间运行的操作,如执行HTTP请求。 – 2012-07-23 12:33:23

+0

在你的代码中,我没有找到任何http请求...! – MAC 2012-07-23 13:02:43

+0

“while循环”之上的一行是注释//将会有一些HttpClient.execute() – 2012-07-23 13:13:28

3

如果您的意思是“是否有机会取消在android.content.AsyncTaskLoader中运行AsyncTask?”答案是肯定的:您只需要在loadInBackground方法中添加一些“取消点”并检查是否发出取消请求(isLoadInBackgroundCanceled()== true),然后返回或抛出一个OperationCanceledException)。

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

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

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

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