Android的AsyncTaskLoader不启动loadInBackground?

我想在Android上实现一个加载器的例子,但无法启动加载器。 我正在使用下面的代码。 它会打“创build加载程序”,但它永远不会到达“加载启动”日志消息。 我错过了我需要的电话吗?

活动:

public class TestingZoneActivity extends ListActivity implements LoaderCallbacks<ArrayList<Content>>{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); getLoaderManager().initLoader(0, null, this); } @Override public Loader<ArrayList<Content>> onCreateLoader(int id, Bundle args) { Log.e("TEST", "Create Loader"); return new ImageLoader(this); } @Override public void onLoadFinished(Loader<ArrayList<Content>> loader, ArrayList<Content> data) { setListAdapter(new ImageAdapter(this, data)); } @Override public void onLoaderReset(Loader<ArrayList<Content>> loader) { setListAdapter(null); } } 

装载机:

  public class ImageLoader extends AsyncTaskLoader<ArrayList<Content>> { public ImageLoader(Context context) { super(context); } @Override public ArrayList<Content> loadInBackground() { Log.e("TEST", "Loading started"); } } 

我有使用兼容性库相同的问题。 我通过调用forceLoad来解决它

 getLoaderManager().initLoader(0, null, this).forceLoad(); 

很显然,关于AsyncLoader的文档是缺乏的,HoneyComb也存在这个问题。 更多信息可以在这里find

AsyncTaskLoader的官方示例也是调用forceLoad(),所以它不是一个bug,但我仍然认为这种行为不是很直观。

重写loadInBackground()是不够的。

看看http://developer.android.com/reference/android/content/AsyncTaskLoader.html上的;AppListLoader

至less将这两个方法添加到您的加载器:

  @Override protected void onStartLoading() { if (takeContentChanged()) forceLoad(); } @Override protected void onStopLoading() { cancelLoad(); } 

并从其构造函数中调用onContentChanged()

rrayst的build议是相当紧凑的。 如果你这样写你的方法:

 protected void onStartLoading() { forceLoad(); } 

你会注意到,当一个孩子的活动出现,然后你回到父母, onStartLoading (和loadInBackground )再次被调用!

你能做什么? 在构造函数中设置一个内部variables( mContentChanged )为true; 然后在onStartLoading检查这个variables。 只有当这是真的,开始加载真实:

 package example.util; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; public abstract class ATLoader<D> extends AsyncTaskLoader<D> { public ATLoader(Context context) { super(context); // run only once onContentChanged(); } @Override protected void onStartLoading() { // That's how we start every AsyncTaskLoader... // - code snippet from android.content.CursorLoader (method onStartLoading) if (takeContentChanged()) { forceLoad(); } } @Override protected void onStopLoading() { cancelLoad(); } } 

既然这里的答案(除了被接受的答案)都没有帮助我解决这个问题,那么这就是我的工作方式。

我不认为接受的答案是正确的解决scheme,因为它会导致loadInBackground()被调用的次数超过必要的,也就是在方向改变的时候,在正确的重载下面的方法的时候也不会发生:

 @Override public void deliverResult(final List<Participant> data) { participants = data; if (isStarted()) { super.deliverResult(data); } } @Override protected void onStartLoading() { if (takeContentChanged() || participants == null) { forceLoad(); } } 

如果您正在使用自定义加载程序,则可以保存最后的数据引用,并通过获取程序使其可用。 当用户旋转他的屏幕时,可以从getLoaderManager()。getLoader方法获取加载器,然后返回引用。 对于我的testing,我注意到startLoadering一直到CustomLoader.onLoadFinished,但结果永远不会传递给activity.onLoadFinished.I怀疑活动引用在循环中丢失。 顺便说一下,创build加载器的好处是通过LoaderManager持久化。 把它想象成另一种无头碎片的味道..哈哈。

 Loader loader = getLoaderManager().getLoader(LOADER_ID); if( loader == null ) { getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this ); } else { listAdapter.addAll(((CustomLoader) loader).getLastData()); } 

我发现上面的每个解决scheme都有问题,特别是当应用程序在屏幕closures时启动,加载需要一些时间。

这是我的解决scheme(基于 ):

 public abstract class AsyncTaskLoaderEx<T> extends AsyncTaskLoader<T> { private static final AtomicInteger sCurrentUniqueId = new AtomicInteger(0); private T mData; public boolean hasResult = false; public static int getNewUniqueLoaderId() { return sCurrentUniqueId.getAndIncrement(); } public AsyncTaskLoaderEx(final Context context) { super(context); onContentChanged(); } @Override protected void onStartLoading() { if (takeContentChanged()) forceLoad(); else if (hasResult) deliverResult(mData); } @Override public void deliverResult(final T data) { mData = data; hasResult = true; super.deliverResult(data); } @Override protected void onReset() { super.onReset(); onStopLoading(); if (hasResult) { onReleaseResources(mData); mData = null; hasResult = false; } } protected void onReleaseResources(T data) { //nothing to do. } public T getResult() { return mData; } }