0

У меня проблема с провайдером содержимого Android с помощью loadermanager. Я использую LoaderManager для загрузки моего CursorLoader из ContentProvider, а ContentProvider вызывает мой класс sqlite. В классе Sqlite я вызываю sql-запрос и возвращаю курсор, не закрывая курсор или базу данных. Как я понял, вот как он должен работать (и он не работает, когда я закрываю курсор/db), но после второго посещения в действии я получаю это исключение из того, что база данных не закрывается. Это должно быть что-то глупое.Закрытие никогда не вызывалось при использовании ContentProvider

Я вызываю initLoader LoaderManager в свой onActivityCreated моего фрагмента.

Вот мой метод запроса в 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); 
    } 
} 

Любая помощь будет высоко ценится!

Edit: Вот мой 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); 
    } 
} 
+0

проблема с вашей реализацией 'LoaderManager.LoaderCallbacks ' (вы не называете swapCursor адаптера или не закрываете курсор) не с этим кодом – Selvin

+0

Спасибо, я отредактировал сообщение и добавил мой код с LoaderCallbacks. Я использую swapCursor там. Где мне закрыть курсор? –

+0

Что делать updateData ... если вы используете адаптер, вы должны вызывать только «adapter.swapCursor (песни);' in 'onLoadFinished' ... вот почему я люблю ContentProviders ... если вы не используете адаптер (одна строка без адаптера/ListView), затем закройте курсор в конце updateData – Selvin

ответ

0

После некоторого времени я наконец-то фиксированное все. Первоначально была вызвана ошибка, потому что мой класс db не был singleton, и каждый вызов создал новый экземпляр подключения к базе данных, поэтому старая ссылка была потеряна, и ContentProvder не смог ее закрыть. В основном я пришел к следующему:

  • Класс Db как singleton, он удалил большинство моих проблем.
  • Я закрываю курсор в onPause и перед каждым вызовом restartLoader.

Теперь у меня есть 3 одновременных загрузчика контента в 3 фрагментах, и они работают нормально.