在http://developer.android.com/guide/components/loaders.html找到的Loaders的Android文档中,它说装载程序的一个属性是:
在配置更改后重新创建时,它们会自动重新连接到上一个加载程序的游标。因此,他们不需要重新查询他们的数据。
以下代码似乎没有镜像该行为,创建了一个新的Loader并完成了对ContentResolver的查询,然后我旋转了屏幕并重新创建了Loader!
public class ReportFragment extends Fragment implements LoaderCallbacks<Cursor> {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(1, null, this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_report, container, false);
return v;
}
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
Log.d("TEST", "Creating loader");
return new CursorLoader(getActivity(), ResourcesContract.Reports.CONTENT_URI, null, null, null, null);
}
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
Log.d("TEST", "Load finished");
}
public void onLoaderReset(Loader<Cursor> arg0) {
}
}
以下是我的logcat的输出:
08-17 16:49:54.474: D/TEST(1833): Creating loader
08-17 16:49:55.074: D/TEST(1833): Load finished
*Here I rotate the screen*
08-17 16:50:38.115: D/TEST(1833): Creating loader
08-17 16:50:38.353: D/TEST(1833): Load finished
知道我在这里做错了吗?
修改
我应该注意,我正在构建Android Google API的版本8,并使用v4支持库。
第二次编辑:
这很可能是由于支持库中存在错误,如果您想了解更多信息,请查看此错误提交:
答案 0 :(得分:1)
虽然这是一个老问题,但我一直遇到与OP相同的问题。使用加载器,我需要在导航到新的Activity时重新启动,然后再返回。但与此同时,当我旋转手机的屏幕时,我不想让装载机重新启动。
我发现如果在调用super之前重新启动加载器,就可以在onRestart()中实现这一点。
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
//Initialize the loader.
getSupportLoaderManager().initLoader(0, null, this);
}
@Override
protected void onRestart() {
//Restart the loader before calling the super.
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
super.onRestart();
}
...
}
答案 1 :(得分:0)
到目前为止,我发现保留片段Fragment.setRetainInstance(true)
可以防止使用支持库在方向更改时重新创建加载器。加载器的最后结果很好地在onLoadFinished()
中传递。它至少在活动管理单个片段时起作用,并且使用FragmentTransaction
将片段添加到活动中。
答案 2 :(得分:0)
虽然这是一个有点老问题,但我想在此提出意见。
无需在onSaveInstanceState
中存储其他信息在配置更改后重新创建框架时,框架会自动重新连接到最后一个加载器的游标。因此,他们不需要重新查询他们的数据。
这意味着在onCreate函数中,只有在savedInstanceState为null时才需要调用loaderManager
例如:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
getLoaderManager().initLoader(1, null, this);
}
}
答案 3 :(得分:0)
在我看来,你误解了文档所说的内容。文档说,他们不需要重新查询他们的数据,但它没有这样做。
尝试在ContentProvider#query()
方法中记录/插入断点!查询将仅在活动启动时调用,而不是在方向更改后调用。
但LoaderCallbacks#onCreateLoader()
方法并非如此。它将在每次方向更改后调用,但这并不意味着重新查询,它只是调用方法,以便您可以根据需要更改CursorLoader。
答案 4 :(得分:-1)
您只需检查加载器上是否已存在加载器。然后你可以初始化或重新启动。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getLoaderManager().getLoader(LOADER_ID) == null) {
getLoaderManager().initLoader(LOADER_ID, null, this);
} else {
getLoaderManager().restartLoader(LOADER_ID);
}
}
您通常会将ID传递给加载程序,以便稍后通过加载程序管理器引用它。
希望这有帮助!
答案 5 :(得分:-2)
onCreate()在屏幕方向更改期间被调用,因为活动被销毁并重新创建。
除非您正在加载大量数据,否则这样做并没有什么坏处,但如果您愿意,可以尝试以下方法(我没有测试过,但理论上我认为它会起作用)。
在类的顶部全局声明一个静态布尔值。我想你还需要一个静态游标来引用
private static boolean dataDownloaded = false;
private static Cursor oldCursor;
然后在onLoadFinished上设置dataDownloaded = true
覆盖onSaveInstanceState以保存布尔值
@Override
protected void onSaveInstanceState(Bundle outSave) {
outSave.putBoolen("datadownloaded", dataDownloaded);
oldCursor = adapter.swapCursor(null);
}
和onCreate添加以下内容
if (savedInstanceState != null) {
this.dataDownloaded = savedInstanceState.getBoolean("datadownloaded", false);
}
调整你的onCreateLoader
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader cursorLoader;
if (dataDownloaded) {
cursorLoader = new CursorLoader(getActivity(),
null, projection, null, null, null);
cursorLoader.deliverResult(oldCursor);
} else {
CursorLoader cursorLoader = new CursorLoader(getActivity(),
URI_PATH, projection, null, null, null);
}
return cursorLoader;
}