Android 为什么我的碎片在重新加载加载程序时会崩溃?

Android 为什么我的碎片在重新加载加载程序时会崩溃?,android,android-fragments,android-loadermanager,Android,Android Fragments,Android Loadermanager,虽然我一直无法复制这个bug,但我仍然会收到一些发生这种情况的崩溃报告。我以为为我的列表适配器添加一个空检查可以修复它,但它仍然在发生。我错过了什么 完整堆栈跟踪: public void onLoaderReset(加载程序){ final int id=loader.getId(); 开关(id){ 案例加载器\u ID1: 如果(mAdapter!=null) mAdapter.changeCursor(null);//stacktrace引用的第512行 打破 案例加载器\u ID2:

虽然我一直无法复制这个bug,但我仍然会收到一些发生这种情况的崩溃报告。我以为为我的列表适配器添加一个空检查可以修复它,但它仍然在发生。我错过了什么

完整堆栈跟踪:

public void onLoaderReset(加载程序){
final int id=loader.getId();
开关(id){
案例加载器\u ID1:
如果(mAdapter!=null)
mAdapter.changeCursor(null);//stacktrace引用的第512行
打破
案例加载器\u ID2:
//这里还有其他代码
打破
违约:
抛出新的InvalidParameterException(“id=”+id);
}
}

mAdapter是在onActivityCreated中初始化的,但我意识到在键入此命令时,我从未发布过它,也许我应该在OnDetch中执行此操作?mAdapter附加到由ListFragment设置的ListView。我将适配器光标设置为null以清除我的列表。那么,是的,我忽略了什么呢?

在搜索了Android源代码之后,我现在明白了,就像GreyBearedGeek所说的那样,我应该允许加载程序处理光标销毁

正如您在CursorLoader中看到的,如果传递新光标,它将处理关闭旧光标的问题:

    /* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
    if (isReset()) {
        // An async query came in while the loader is stopped
        if (cursor != null) {
            cursor.close();
        }
        return;
    }
    Cursor oldCursor = mCursor;
    mCursor = cursor;

    if (isStarted()) {
        super.deliverResult(cursor);
    }

    if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
        oldCursor.close();
    }
}
以及在重置时关闭光标

    @Override
protected void onReset() {
    super.onReset();

    // Ensure the loader is stopped
    onStopLoading();

    if (mCursor != null && !mCursor.isClosed()) {
        mCursor.close();
    }
    mCursor = null;
}

因此,我将在将来使用swapCursor,以避免干扰游标装载机的处理,尽管我还不知道这是如何导致我的NPE出现在上面的堆栈跟踪中。

我无法想象它是您的NPE的来源,但是我认为您应该使用
swapCursor
而不是
changeCursor
,因为加载程序“拥有”光标并将其关闭
swapCursor
不会关闭旧的游标,而
changeCursor
会关闭。我明白你现在说的话,我会看看是否可以复制它,这样我就可以尝试你的解决方案。当然,54142()问题表明了我认为会发生的事情。好吧,这是一个我(我想大多数人)不知道的非常严重的错误:-)
    @Override
protected void onReset() {
    super.onReset();

    // Ensure the loader is stopped
    onStopLoading();

    if (mCursor != null && !mCursor.isClosed()) {
        mCursor.close();
    }
    mCursor = null;
}