使用ContentProvider时从未专门调用Close

时间:2014-09-23 13:23:37

标签: java android sqlite android-contentprovider android-loadermanager

我在使用loadermanager时遇到了android内容提供程序的问题。我正在使用LoaderManager从ContentProvider加载我的CursorLoader,而ContentProvider正在调用我的sqlite类。 在Sqlite类中,我调用sql查询并返回游标,而不是关闭游标或数据库。 据我所知,它是如何工作的(当我关闭游标/数据库时它不起作用),但在第二次访问活动后,我得到关于数据库没有关闭的这个例外。它一定是蠢事。

我在我片段的onActivityCreated中调用了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子类):

public Cursor getAllSongs(String order) {
    SQLiteDatabase db = null;
    Cursor cursor;
    try {
        db = this.getReadableDatabase();
        String sql = "";
        sql += "select " + Constants.AUTHOR_SELECT_COLUMNS + ", " + Constants.SONG_SELECT_COLUMNS + ", " + Constants.GLOBAL_ID;
        sql += " from " + Constants.SONG_TABLE_NAME + ", " + Constants.AUTHOR_TABLE_NAME + " ";
        sql += " where " + Constants.SONG_TABLE_NAME + "." + Constants.AUTHOR_FK + " = " + Constants.AUTHOR_TABLE_NAME + "." + Constants.AUTHOR_ID + " AND  " + Constants.SONG_TABLE_NAME + "."
                + Constants.SONG_SOURCE_TYPE + " = " + Constants.AUTHOR_TABLE_NAME + "." + Constants.AUTHOR_SOURCE_TYPE;
        // sql += " order by " + Constants.AUTHOR_TABLE_NAME + "." +
        // Constants.AUTHOR_NAME + COLLATE;
        sql += order;
        // sql += " limit 20 ";
        cursor = db.rawQuery(sql, new String[] {});
        return cursor;
    } finally {
        //closeQuietly(db);
    }
}

非常感谢任何帮助!

编辑: 这是我的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);
}

EDIT2:

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);
    }
}

1 个答案:

答案 0 :(得分:0)

经过一段时间后,我终于解决了所有问题。最初导致错误,因为我的db类不是单例,并且每次调用都创建了新的数据库连接实例,因此旧的引用丢失了,而ContentProvder无法关闭它。基本上我来到这里:

  • Db类作为单身,它删除了我的大多数问题。
  • 我在onPause和每次restartLoader调用之前关闭游标。

现在我在3个片段中有3个并发的内容加载器,它们工作正常。