Java 使用ContentProvider时从未专门调用Close

Java 使用ContentProvider时从未专门调用Close,java,android,sqlite,android-contentprovider,android-loadermanager,Java,Android,Sqlite,Android Contentprovider,Android Loadermanager,我与loadermanager的android内容提供商有问题。我正在使用LoaderManager从ContentProvider加载我的游标Loader,ContentProvider正在调用我的sqlite类。 在Sqlite类中,我调用sql查询并返回游标,而不是关闭游标或数据库。 据我所知,这就是它应该如何工作的(当我关闭cursor/db时它不工作),但在活动中第二次访问之后,我得到了关于数据库未关闭的异常。一定是什么蠢事 我正在调用onActivityCreated of my f

我与loadermanager的android内容提供商有问题。我正在使用LoaderManager从ContentProvider加载我的游标Loader,ContentProvider正在调用我的sqlite类。 在Sqlite类中,我调用sql查询并返回游标,而不是关闭游标或数据库。 据我所知,这就是它应该如何工作的(当我关闭cursor/db时它不工作),但在活动中第二次访问之后,我得到了关于数据库未关闭的异常。一定是什么蠢事

我正在调用onActivityCreated of my fragment中LoaderManager的initLoader

以下是我在ContentProvider中的查询方法:

public synchronized Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
    final SongDbHandler songDbHandler = AbstractActivity.getLocalService(getContext()).getDbHandler();
    String order = " ";
    if ("author".equals(sortOrder)) {
        order = Constants.ORDER_AUTHOR;
    } else if ("song".equals(sortOrder)) {
        order = Constants.ORDER_SONG;
    }
    System.out.println("getAllSongs");
    final Cursor cursor = songDbHandler.getAllSongs(order);
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}
以下是我在sqlite类(singleton SQLiteOpenHelper子类)中的代码:

任何帮助都将不胜感激

编辑: 这是我的LoaderManager回调:

@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
    return (Loader<Cursor>) new CursorLoader(getActivity().getApplicationContext(), SongContentProvider.getLocalProviderUri(), null, null, null, bundle.getString("order"));
}

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor songs) {
    updateData(songs);
}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    adapter.swapCursor(null);
}

过了一段时间,我终于把一切都修好了。错误最初是由以下原因引起的:我的db类不是singleton,每次调用都会创建新的数据库连接实例,所以旧引用丢失,ContentProvider无法关闭它。基本上我是这样想的:

  • Db类作为单例,它消除了我的大部分问题
  • 在每次重新启动加载程序调用之前,我都会在暂停时关闭光标

现在我有3个并发ContentLoader,分为3个片段,它们工作正常。

问题在于您的
LoaderManager.LoaderCallbacks的实现。
(您不调用适配器的swapCursor或不关闭光标)不使用此代码谢谢,我编辑了文章并使用LoaderCallbacks添加了代码。我在那里用的是swapCursor。我应该在哪里关闭光标?updateData在做什么。。。如果您使用的是adapter,您应该只调用
adapter.swapCursor(歌曲)
onLoadFinished
。。。这就是为什么我喜欢内容提供商。。。如果您没有使用适配器(单行,没有适配器/ListView),请再次关闭UpdateDateEdit末尾的歌曲光标-如果没有结果,我只是显示信息。那么这里应该没有问题。。。不要在ContentProvider实现之外使用SongDbHandler在ContentProvider的onCreate中仅创建此类的一个实例。。。(强制您不要在CP外部使用它,使SongDbHandler成为CP的内部静态类)。。。
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
    return (Loader<Cursor>) new CursorLoader(getActivity().getApplicationContext(), SongContentProvider.getLocalProviderUri(), null, null, null, bundle.getString("order"));
}

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor songs) {
    updateData(songs);
}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    adapter.swapCursor(null);
}
private void updateData(Cursor songs) {
    adapter.swapCursor(songs);
    if (songs == null || songs.getCount() == 0) {
        vysledky.setVisibility(View.GONE);
        vysledkyMsg.setText(getString(R.string.no_results));
        vysledkyMsg.setVisibility(View.VISIBLE);
    } else {
        vysledky.setVisibility(View.VISIBLE);
        vysledkyMsg.setText(getString(R.string.progress_loading_content));
        vysledkyMsg.setVisibility(View.GONE);
    }
}