我有一个具有列表视图的片段。
在 onPause() 中,我将列表视图的 Y 滚动位置保存在 ContentProvider 中。
onResume 或 onActivityCreated 上的相同片段使用加载器从 contentprovider 获取该 y 滚动位置并恢复滚动位置。
如果我退出活动/片段并返回到它,这将起作用,列表视图将返回到其上次打开的位置,因为它已在 onPause 中保存到 contentprovider。所以代码是 100% 没问题的。
不好的是轮换数据。onPause 保存得很好,但是 onCreateActivity 之后的加载导致检索旧数据,即在 onPause 中保存之前的数据。当他们第一次打开应用程序时,它会导致列表视图返回到旧位置,而不是列表视图在旋转之前的位置。
似乎一个明显的竞争条件是 onPause 期间向内容提供者的保存未在 onPause 中完成,导致在旋转后加载旧数据。
所以我手机上的旋转看起来像这样
01:31:33.026: ThreadViewerFragment.java(235):onPause Saved(position:Yposition): 59:-74
01:31:33.256: ThreadViewerFragment.java(194):onActivityCreated
01:31:33.266: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 62:-149 //initial load is of old values
01:31:33.266: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 62:-149
01:31:33.596: ThreadViewerFragment.java(309):onLoadFinished Load(position:Yposition): 59:-74 //this is loaded due to notification by the save in onPause which is supposed to be finished before recreating the new fragment???
所以顺序看起来不错(在活动/片段流方面看起来不像是竞争条件)但很明显,它加载了旧值而不是刚刚保存的 59:-74 值。
我不是在解决问题,我知道如何使用 saveInstanceState 等。但是为什么我要加倍我的代码,有没有办法强制 contentprovider 以原子方式运行(我认为它已经是?)
编辑:添加代码并更好地改进问题,因为我仍然不满意我们更接近于理解 contentprovider 调用是否在执行时阻塞和/或这些调用是否是原子的,或者它只是对 contentprovider 和加载器的误解.
在 onPause 中,我正在保存产品列表的 Y 位置
@Override
public void onPause() {
super.onPause();
Utils.logv("onPause Saved position: " + mLastRead + ", " + mYPos);
ContentValues contentValues = new ContentValues();
contentValues.put(ProductsContract.Products.Y_POS, mYpos);
int updateCount = getActivity().getContentResolver().update(
Uri.parse(ProductsContract.Products.CONTENT_URI + "/" + mId),
contentValues, null, null);
}
我的理解是更新调用应该是阻塞调用,它发生在片段被销毁之前和创建新片段以处理旋转之前
在简历中我启动了我的装载机
public void onResume() {
super.onResume();
getLoaderManager().initLoader(PRODUCTS_LOADER_ID, null, this);
}
在我的加载器中,我得到了光标,它在旋转后可靠地具有旧数据,但在任何其他情况下都可以
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
if(cursor.moveToFirst()){
mYpos = cursor.getInt(cursor.getColumnIndex(ProductsContract.Products.Y_POS));
Utils.logv("loader: " + mYpos);
}
}
所以重申,在轮换之后,加载器将始终如一地传递旧数据。
我在想也许是陈旧的加载器而不是内容提供者本身?即使光标过时,光标也会在旋转后保存和恢复?