我想用一个演示来展示:
enter code here
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(buttonClickListener);
}
private OnClickListener buttonClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startMyLoader();
}
};
private void startMyLoader() {
getLoaderManager().destroyLoader(0);
getLoaderManager().restartLoader(0, null, myLoaderListener);
}
/**
* The listener for the group metadata loader.
*/
private final LoaderManager.LoaderCallbacks<Cursor> myLoaderListener
= new LoaderCallbacks<Cursor>() {
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
return new CursorLoader(LoaderDemoActivity.this,
ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
cursor.moveToPosition(-1);
if (cursor.moveToNext()) {
Context context = getApplicationContext();
CharSequence text = "Load finished!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
enter code here
改变方向后,我点击了按钮, 可以调用onCreateLoader, 但onLoadFinished将不会被调用。
看起来很奇怪。
提前感谢您的帮助。
答案 0 :(得分:14)
我遇到了同样的问题。请在onCreate中尝试调用this.getSupportLoaderManager()。 它解决了我的问题。希望它也能帮助你
答案 1 :(得分:5)
我想我找到了原因。
在Activity onCreate中,它将加载所有LoaderMangers(自己的或其子片段) 来自NonConfigurationInstances。
if (mLastNonConfigurationInstances != null) {
mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
}
在Activity onStart中,它将尝试启动自己的LoaderManger。
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
但是在配置改变之后,mLoaderManager == null,所以它不会启动它。 这就是问题所在! 如果你尝试启动加载器属于这个loaderManager,它将失败。
void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
// The activity will start all existing loaders in it's onStart(),
// so only start them here if we're past that point of the activitiy's
// life cycle
info.start();
}
}
注意mStarted值,当LoaderManager启动时,该值将设置为“true”。
有两种方法可以解决这个问题。
在onCreate()中调用getLoaderManger(),它将重新分配mLoaderManager 并准备好在subseuqent onStart()中启动。
public LoaderManager getLoaderManager(){ if(mLoaderManager!= null){ 返回mLoaderManager; } mCheckedForLoaderManager = true; mLoaderManager = getLoaderManager(-1,mLoadersStarted,true); 返回mLoaderManager; }
将装载程序放在碎片中。因为在Fragments的onStart()中, 它将启动自己的LoaderManager。
if(!mLoadersStarted){ mLoadersStarted = true; if(!mCheckedForLoaderManager){ mCheckedForLoaderManager = true; mLoaderManager = mActivity.getLoaderManager(mIndex,mLoadersStarted,false); } if(mLoaderManager!= null){ mLoaderManager.doStart(); } }
答案 2 :(得分:3)
您不需要(也不应该)销毁Loader
以重新加载它。 Loader
类旨在可重用。
请改用initLoader
。例如:
getLoaderManager().initLoader(0, null, myLoaderListener);
如果你想强制重新加载已经注册的加载器:
getLoaderManager().getLoader(0).forceLoad();
如果在配置更改事件发生后您不确定Loader
实例是否已存在,请使用initLoader
代替getLoader
来检索您可以调用的Loader
实例forceLoad()
。
getLoaderManager().initLoader(0, null, myLoaderListener).forceLoad();
如果你使用支持库,那么即使在第一次即时之后也使用forceLoad
- 可能存在一个错误 - 我提醒自己在这个论坛上有一些关于它的问题 - 尝试搜索较旧的帖子。
答案 3 :(得分:1)
在活动savedStateInfo
中调用您的加载程序之前,请确保您在使用片段时未检查onCreate
@Override
public void onCreate(Bundle savedInstanceState) {
// used to not overlap fragments
if (savedInstanceState != null) {
return null;
}
loadFragments();
getSupportLoaderManager().restartLoader(LISTS_LOADER, null, this);
}
如果你需要检查savedInstanceState
片段,你可以检查加载完成加载后应该创建的任何类变量,因为活动在旋转时会被破坏,但在旋转时会从之前的状态升起。
答案 4 :(得分:0)
来自android的开发网站
“它们会自动重新连接到最后一个加载器的光标 配置更改后重新创建。因此,他们不需要 重新查询他们的数据。“
据我所知,即使我们明确地启动加载器,加载器也不会启动。因为我们调用的destroy实际上应该在它被销毁后调用onLoaderReset()
。但是一旦方向改变,就不会调用该方法,但之前会调用该方法。
我仍然可能错了。这是我的假设。将进一步讨论。