适用于Android的游标中的竞争条件?

时间:2015-08-02 05:08:19

标签: android cursor race-condition

所以我有这个应用程序通过提供程序将数据加载到游标中。 然后,光标用于获取要使用的应用程序的数据。 加载过程使用LoaderManager API完成。

现在,在某些情况下我从swapCursor()致电onLoadFinished()后问题出现了;光标报告具有正确数量的数据,但当我尝试访问它时,我得到CursorIndexOutOfBoundsException

奇怪的是,我确切地知道它出现在哪一行上,所以我在那里放了一个断点来挂起所有线程并试图检查数据以查看是什么,突然错误消失了。

现在通过反复试验,我发现即使我什么也不做,问题就会消失。就像暂停一切之后没有任何东西一样。如果我在恢复执行之前等待几秒钟,那么数据就可以完全访问。

所以我的问题是:有人知道Android操作系统是否在后台创建竞争条件吗?我没有真正看到这可能是我身边的一个错误,因为当我测试它时我暂停了所有线程,所以我的应用程序在等待问题解决时无法做任何事情。

作为旁注,如果我只是用swapCursor()替换changeCursor()来电(这意味着我必须使用restartLoader()代替initLoader(),因为其他一些功能系统)bug消失了,但是我已经在某个地方读到这不是正确的方法,因为它没有正确处理光标的关闭(我认为这就是我的原因)使用restartLoader(),但我现在无法回想起来。)

部分代码摘录:

@Override
public void onCreate( Bundle savedInstanceState ) {
    super.onCreate( savedInstanceState );
    ...
    getLoaderManager().initLoader( ACTIVE_TEAM_LOADER, null, this );
}

...

@Override
public void onLoadFinished( Loader<Cursor> loader, Cursor data ) {
    switch ( loader.getId() ) {
    case ACTIVE_TEAM_LOADER:
        activeTeamAdapter.swapCursor(
            new MergeCursor( new Cursor[]{ data, createNewCursor } ) );
...
}

违规行,在CursorAdapter.bindView()

的堆栈深处
long value = data.getLong( data.getColumnIndex( getDBName() ) );

对我来说,看起来光标中的数据尚未正确加载。

1 个答案:

答案 0 :(得分:0)

问题是由: this()未关闭之前的swapCursor()光标引起的。关闭前一个光标解决了问题,但引入了一个新问题,因为你不应该关闭来自MergeCursor的游标,当关闭onLoadFinished()时,MergeCursor也会关闭所有子游标

每当我使用适配器仅显示MergeCursor时(某些适配器显示changeCursor() s和MergeCursor s时,切换回使用MergeCursor即可解决此问题没有来自MatrixCursor的数据,由于某种原因onLoadFinished()似乎需要在用法之间关闭,所以这不适用于他们,我不知道为什么)并且包含任何游标一个无视结束的课程。

MatrixCursor摘录:

onLoadFinished()

包装器:

Cursor[] cursors = new Cursor[] { new UnclosableCursor( data ), createNewCursor };
activeTeamAdapter.changeCursor( new MergeCursor( cursors ) );

此答案的先前版本暗示这与铸造有关,但经过更多研究后,这似乎只是问题的症状,而不是实际问题。