Java 防止AsyncTask在bindView中多次运行

Java 防止AsyncTask在bindView中多次运行,java,android,android-asynctask,android-cursoradapter,Java,Android,Android Asynctask,Android Cursoradapter,我有一个自定义的CursorAdapter,它在bindView方法中使用多个AsyncTasks将图像加载到网格中 当bindView运行我的AsyncTasks时,会多次启动。这会增加堆大小,并可能导致内存不足错误 让AsyncTasks只运行一次的最佳方法是什么?您可以缓存AsyncTask的结果。在Github上有一个非常有用的项目,您可能想研究一下。我想您正在寻找它或它的实现。它为你处理一切 如何使用它的示例: public SampleLoader extends AsyncTask

我有一个自定义的
CursorAdapter
,它在
bindView
方法中使用多个
AsyncTask
s将图像加载到网格中

bindView
运行我的
AsyncTask
s时,会多次启动。这会增加堆大小,并可能导致内存不足错误


AsyncTask
s只运行一次的最佳方法是什么?

您可以缓存AsyncTask的结果。在Github上有一个非常有用的项目,您可能想研究一下。

我想您正在寻找它或它的实现。它为你处理一切

如何使用它的示例:

public SampleLoader extends AsyncTaskLoader<List<SampleItem>> {

  // We hold a reference to the Loader’s data here.
  private List<SampleItem> mData;

  public SampleLoader(Context ctx) {
    // Loaders may be used across multiple Activitys (assuming they aren't
    // bound to the LoaderManager), so NEVER hold a reference to the context
    // directly. Doing so will cause you to leak an entire Activity's context.
    // The superclass constructor will store a reference to the Application
    // Context instead, and can be retrieved with a call to getContext().
    super(ctx);
  }

  /****************************************************/
  /** (1) A task that performs the asynchronous load **/
  /****************************************************/

  @Override
  public List<SampleItem> loadInBackground() {
    // This method is called on a background thread and should generate a
    // new set of data to be delivered back to the client.
    List<SampleItem> data = new ArrayList<SampleItem>();

    // TODO: Perform the query here and add the results to 'data'.

    return data;
  }

  /********************************************************/
  /** (2) Deliver the results to the registered listener **/
  /********************************************************/

  @Override
  public void deliverResult(List<SampleItem> data) {
    if (isReset()) {
      // The Loader has been reset; ignore the result and invalidate the data.
      releaseResources(data);
      return;
    }

    // Hold a reference to the old data so it doesn't get garbag ecollected.
    // We must protect it until the new data has been delivered.
    List<SampleItem> oldData = mData;
    mData = data;

    if (isStarted()) {
      // If the Loader is in a started state, deliver the results to the
      // client. The superclass method does this for us.
      super.deliverResult(data);
    }

    // Invalidate the old data as we don't need it any more.
    if (oldData != null && oldData != data) {
      releaseResources(oldData);
    }
  }

  /*********************************************************/
  /** (3) Implement the Loader’s state-dependent behavior **/
  /*********************************************************/

  @Override
  protected void onStartLoading() {
    if (mData != null) {
      // Deliver any previously loaded data immediately.
      deliverResult(mData);
    }

    // Begin monitoring the underlying data source.
    if (mObserver == null) {
      mObserver = new SampleObserver();
      // TODO: register the observer
    }

    if (takeContentChanged() || mData == null) {
      // When the observer detects a change, it should call onContentChanged()
      // on the Loader, which will cause the next call to takeContentChanged()
      // to return true. If this is ever the case (or if the current data is
      // null), we force a new load.
      forceLoad();
    }
  }

  @Override
  protected void onStopLoading() {
    // The Loader is in a stopped state, so we should attempt to cancel the
    // current load (if there is one).
    cancelLoad();

    // Note that we leave the observer as is. Loaders in a stopped state
    // should still monitor the data source for changes so that the Loader
    // will know to force a new load if it is ever started again.
  }

  @Override
  protected void onReset() {
    // Ensure the loader has been stopped.
    onStopLoading();

    // At this point we can release the resources associated with 'mData'.
    if (mData != null) {
      releaseResources(mData);
      mData = null;
    }

    // The Loader is being reset, so we should stop monitoring for changes.
    if (mObserver != null) {
      // TODO: unregister the observer
      mObserver = null;
    }
  }

  @Override
  public void onCanceled(List<SampleItem> data) {
    // Attempt to cancel the current asynchronous load.
    super.onCanceled(data);

    // The load has been canceled, so we should release the resources
    // associated with 'data'.
    releaseResources(data);
  }

  private void releaseResources(List<SampleItem> data) {
    // For a simple List, there is nothing to do. For something like a Cursor, we
    // would close it in this method. All resources associated with the Loader
    // should be released here.
  }

  /*********************************************************************/
  /** (4) Observer which receives notifications when the data changes **/
  /*********************************************************************/

  // NOTE: Implementing an observer is outside the scope of this post (this example
  // uses a made-up "SampleObserver" to illustrate when/where the observer should
  // be initialized).

  // The observer could be anything so long as it is able to detect content changes
  // and report them to the loader with a call to onContentChanged(). For example,
  // if you were writing a Loader which loads a list of all installed applications
  // on the device, the observer could be a BroadcastReceiver that listens for the
  // ACTION_PACKAGE_ADDED intent, and calls onContentChanged() on the particular
  // Loader whenever the receiver detects that a new application has been installed.
  // Please don’t hesitate to leave a comment if you still find this confusing! :)
  private SampleObserver mObserver;
}
publicSampleLoader扩展了AsyncTaskLoader{
//我们在这里保存了装载机数据的引用。
私有列表数据;
公共样本加载器(上下文ctx){
//装载机可以跨多个活动使用(假设它们不是
//绑定到LoaderManager),因此永远不要保留对上下文的引用
//直接。这样做会导致泄漏整个活动的上下文。
//超类构造函数将存储对应用程序的引用
//相反,可以通过调用getContext()来检索。
超级(ctx);
}
/****************************************************/
/**(1)执行异步加载的任务**/
/****************************************************/
@凌驾
公共列表加载背景(){
//此方法在后台线程上调用,并应生成
//要传递回客户端的新数据集。
列表数据=新的ArrayList();
//TODO:在此处执行查询并将结果添加到“数据”中。
返回数据;
}
/********************************************************/
/**(2)将结果传递给注册的侦听器**/
/********************************************************/
@凌驾
公共无效交付结果(列表数据){
if(isReset()){
//加载程序已重置;忽略结果并使数据无效。
发布资源(数据);
返回;
}
//保留对旧数据的引用,这样它就不会被收集。
//在新数据交付之前,我们必须保护它。
List oldData=mData;
mData=数据;
如果(isStarted()){
//如果加载程序处于启动状态,则将结果传递给
//超类方法为我们做到了这一点。
super.deliverResult(数据);
}
//使旧数据无效,因为我们不再需要它了。
if(oldData!=null&&oldData!=data){
释放资源(旧数据);
}
}
/*********************************************************/
/**(3)实现加载器的状态相关行为**/
/*********************************************************/
@凌驾
开始加载时受保护的void(){
如果(mData!=null){
//立即交付以前加载的任何数据。
交付结果(mData);
}
//开始监视基础数据源。
if(mObserver==null){
mObserver=新的SampleObserver();
//TODO:注册观察者
}
if(takeContentChanged()| | mData==null){
//当观察者检测到更改时,它应该调用onContentChanged()
//在加载程序上,这将导致对takeContentChanged()的下一次调用
//返回true。如果是这种情况(或者如果当前数据为
//null),我们强制一个新的加载。
力载荷();
}
}
@凌驾
受保护的无效onStopLoading(){
//加载程序处于停止状态,因此我们应该尝试取消
//当前负载(如果有)。
取消加载();
//请注意,我们将观察者保持原样。加载程序处于停止状态
//仍应监视数据源的更改,以便加载程序
//如果再次启动,将知道强制加载新负载。
}
@凌驾
受保护的void onReset(){
//确保装载机已停止。
onStopLoading();
//此时,我们可以释放与“mData”关联的资源。
如果(mData!=null){
释放资源(mData);
mData=null;
}
//加载程序正在重置,因此我们应该停止监视更改。
if(mObserver!=null){
//TODO:取消注册观察者
mObserver=null;
}
}
@凌驾
已取消公共作废(列表数据){
//尝试取消当前异步加载。
super.onCanceled(数据);
//加载已取消,因此我们应该释放资源
//与“数据”关联。
发布资源(数据);
}
私有void releaseResources(列表数据){
//对于一个简单的列表,没有什么可以做的
//将在此方法中关闭它。与加载程序关联的所有资源
//应该在这里发布。
}
/*********************************************************************/
/**(4)当数据发生变化时接收通知的观察者**/
/*********************************************************************/
//注意:实现一个观察者超出了本文的范围(本例)
//使用虚构的“SampleObserver”来说明观察者应在何时/何地进行观察
//(无法初始化)。
//观察者可以是任何东西,只要它能够检测到内容的变化
//并通过调用onContentChanged()将它们报告给加载程序。例如,
//如果您正在编写加载所有已安装应用程序列表的加载程序
//在该设备上,观察者可以是一个广播接收器,用于监听信号
//ACTION_PACKAGE_添加了意图,并对特定的
//每当接收器检测到新应用程序已安装时,加载程序。
//如果您仍然感到困惑,请随时发表评论!:)
私有采样服务器;
}

来源:

使用
加载程序
,如前所述@