我正在尝试在Android上实现一个加载器示例,但无法让它启动加载器。我使用以下代码。它将点击“Create Loader”,但它永远不会到达“正在加载”日志消息。我错过了我需要的电话吗?
的活动:
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");
}
}
答案 0 :(得分:128)
使用兼容性库时遇到了同样的问题。
我通过致电forceLoad
getLoaderManager().initLoader(0, null, this).forceLoad();
显然缺少AsyncLoader的文档,HoneyComb上也存在这个问题。可以找到更多信息here
AsyncTaskLoader的官方example也调用forceLoad()所以它不是一个bug,但我仍然认为这种行为不是很直观。
答案 1 :(得分:25)
覆盖loadInBackground()
是不够的。
查看http://developer.android.com/reference/android/content/AsyncTaskLoader.html上的AppListLoader
。
至少将这两种方法添加到您的加载器中:
@Override
protected void onStartLoading() {
if (takeContentChanged())
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
并从其构造函数中调用onContentChanged()
。
答案 2 :(得分:13)
rrayst的建议非常紧凑。如果你这样编写你的方法:
protected void onStartLoading() {
forceLoad();
}
你会注意到当孩子活动出现然后你回到父母活动时,onStartLoading
(以及loadInBackground
)再次被召唤!
你能做什么?
在构造函数中将内部变量(mContentChanged
)设置为true;然后在onStartLoading
中检查此变量。只有当它成立时才开始加载真实:
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();
}
}
答案 3 :(得分:2)
由于这里的答案(除了被接受的答案)都没有帮助我解决这个问题,因此以下是它对我有用的方法。
我不认为接受的答案是正确的解决方案,因为它导致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();
}
}
答案 4 :(得分:0)
如果您使用的是自定义加载程序,则可以保存最后一个数据引用,并通过getter将其提供。当用户旋转屏幕时,您可以从getLoaderManager()。getLoader方法返回加载器,然后返回引用。对于我的测试,我注意到startLoadering一直到CustomLoader.onLoadFinished,但结果永远不会传递给activity.onLoadFinished.I怀疑活动引用在轮换时丢失。顺便说一下,创建加载器的好处是它们通过LoaderManager持久存在。把它想象成无头碎片的另一种味道..哈哈。
Loader loader = getLoaderManager().getLoader(LOADER_ID);
if( loader == null )
{
getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
listAdapter.addAll(((CustomLoader) loader).getLastData());
}
答案 5 :(得分:0)
我发现上述每种解决方案都存在问题,尤其是在屏幕关闭时应用启动时,加载需要一些时间。
这是我的解决方案(基于this):