Страница 1 из 1

Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 30 окт 2013, 22:21
Elek
Здравствуйте.
Имеется простая таблица, ContentProvider для этой таблицы. В таблице есть колонка Favorites, которая хранит 1 или 0.
Еще есть Activity c Listview и кастомным CursorAdapter"om.
При загрузке Activity передаю только строки, в которых столбец Favorites = 1:

onCreateLoader:
[syntax=java]public android.support.v4.content.Loader<Cursor> onCreateLoader(int id,
Bundle args) {
String[] projection = { CurrenciesTable.COLUMN_ID,
CurrenciesTable.COLUMN_ABBREVIATIONS,
CurrenciesTable.COLUMN_CURRENCIES_NAME };
CursorLoader cursorloader = new CursorLoader(this,
CurrenciesContentProvider.CONTENT_URI, projection,
CurrenciesTable.COLUMN_CURRENCIES_FAVORITES + "=?",
new String[] { "1" }, null);
return cursorloader;
}[/syntax]

onLoadFinished:
[syntax=java]
public void onLoadFinished(
android.support.v4.content.Loader<Cursor> loader, Cursor cursor) {
if (currAdapter != null && cursor != null) {
currAdapter.swapCursor(cursor);
}
}[/syntax]

Еще имееться кнопка, при нажатии на которую я показываю все строки в Listview, ну и при повторном нажатии показываю опять только те, в которых Favorites = 1;

Весь этот код выглядит вот так:
[syntax=java]
private void showAll() {
Resources res = getResources();
String showAllText = res.getString(R.string.show_all);
String showFavoritesText = res.getString(R.string.show_favorites);
Cursor cursor = null;
if (!mAllshowed) {
cursor = getContentResolver().query(
CurrenciesContentProvider.CONTENT_URI, null, null, null,
null);
mAllshowed = true;
mBtnShowAll.setText(showFavoritesText);
} else {
String[] projection = { CurrenciesTable.COLUMN_ID,
CurrenciesTable.COLUMN_ABBREVIATIONS,
CurrenciesTable.COLUMN_CURRENCIES_NAME };
cursor = getContentResolver().query(
CurrenciesContentProvider.CONTENT_URI, projection,
CurrenciesTable.COLUMN_CURRENCIES_FAVORITES + "=?",
new String[] { "1" }, null);
mAllshowed = false;
mBtnShowAll.setText(showAllText);
}
currAdapter.swapCursor(cursor);
}
[/syntax]

Все работает и делает то, что от него требуется :) . Но я так понимаю, что код в методе showAll() выполняется в одном с UI потоке. Как правильно это все переделать использую Loader? Подходит ли он для таких вещей, ну и если нет, может объясните, как правильно делать такие вещи :oops: .

Спасибо :)

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 31 окт 2013, 00:17
Foenix
Радует, что кто-то наконец стал разбираться с Loader-ами и ComtentProvider-ами :)
Я бы сделала так.
- Кнопкой меняла бы какой-нибудь флаг (локальную переменную класса).
- в ините лоадера проверяла бы как стоит флаг, а затем выбирала бы в зависимости от этого нужный URI
- (возврщаемся к коду кнопки) передергивала бы лоадер таким кодом getLoaderManager().restartLoader(0, null, this);

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 31 окт 2013, 10:26
Elek
Большое спасибо, сделал так, как вы написали :D .
Сделал 2 константы.
При нажатии на кнопку вызываю метод :

[syntax=java5]private void showAll() {
Resources res = getResources();
String showAllText = res.getString(R.string.show_all);
String showFavoritesText = res.getString(R.string.show_favorites);
if (!mAllshowed) {
getSupportLoaderManager().restartLoader(SHOW_ALL_ID, null,
CurrenciesActivity.this);
mAllshowed = true;
mBtnShowAll.setText(showFavoritesText);
} else {
mAllshowed = false;
getSupportLoaderManager().restartLoader(SHOW_FAVORITES_ID, null,
CurrenciesActivity.this);
mBtnShowAll.setText(showAllText);
}
}[/syntax]

обновил onCreateLoader :
[syntax=java5]public android.support.v4.content.Loader<Cursor> onCreateLoader(int id,
Bundle args) {
CursorLoader cursorloader = null;
switch (id) {
case SHOW_FAVORITES_ID:
String[] projection = { CurrenciesTable.COLUMN_ID,
CurrenciesTable.COLUMN_ABBREVIATIONS,
CurrenciesTable.COLUMN_CURRENCIES_NAME };
cursorloader = new CursorLoader(this,
CurrenciesContentProvider.CONTENT_URI, projection,
CurrenciesTable.COLUMN_CURRENCIES_FAVORITES + "=?",
new String[] { "1" }, null);
return cursorloader;
case SHOW_ALL_ID:
cursorloader = new CursorLoader(getApplicationContext(),
CurrenciesContentProvider.CONTENT_URI, null, null, null,
null);
return cursorloader;

default:
break;
}

return cursorloader;
}[/syntax]

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 31 окт 2013, 13:13
Foenix
Скажем так, достаточно было бы одной переменной-флага пусть даже с константными значениями.
И во-вторых, хоть и получилось, но у тебя при использовании параметра ID, который в onCreateLoader, исказился его смысл. Этот параметр не для передачи туда значения (какого-то абстрактного), а для обозначения в активити нескольких лоадеров (а он по смыслу у тебя один) Поэтому я бы или использовала Bundle, или какое-то свойство активити.

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 05 ноя 2013, 20:23
Elek
Спасибо за наставления :) .
Немного переработал код :

Перезагружает курсор, когда кликаю на кнопку :
[syntax=java5]private void showAll() {
Resources res = getResources();
Bundle bndl = new Bundle();
if (!mAllshowed) {
// show all values
bndl.putInt(BUNDLE_VALUE, SHOW_ALL_ID);
getSupportLoaderManager().restartLoader(0, bndl,
CurrenciesActivity.this);
mAllshowed = true;
String showFavoritesText = res.getString(R.string.show_favorites);
mBtnShowAll.setText(showFavoritesText);
} else {
// show favorites
bndl.putInt(BUNDLE_VALUE, SHOW_FAVORITES_ID);
mAllshowed = false;
getSupportLoaderManager().restartLoader(0, bndl,
CurrenciesActivity.this);
String showAllText = res.getString(R.string.show_all);
mBtnShowAll.setText(showAllText);
}
}[/syntax]

onCreateLoader :

[syntax=java5]@Override
public android.support.v4.content.Loader<Cursor> onCreateLoader(int id,
Bundle bundle) {
CursorLoader cursorloader = null;
int bndlValue = bundle.getInt(BUNDLE_VALUE);
switch (bndlValue) {
case SHOW_FAVORITES_ID:
String[] projection = { CurrenciesTable.COLUMN_ID,
CurrenciesTable.COLUMN_ABBREVIATIONS,
CurrenciesTable.COLUMN_CURRENCIES_NAME,
CurrenciesTable.COLUMN_CURRENCIES_FAVORITES };
cursorloader = new CursorLoader(this,
CurrenciesContentProvider.CONTENT_URI, projection,
CurrenciesTable.COLUMN_CURRENCIES_FAVORITES + "=?",
new String[] { "1" }, null);
return cursorloader;

case SHOW_ALL_ID:
cursorloader = new CursorLoader(getApplicationContext(),
CurrenciesContentProvider.CONTENT_URI, null, null, null,
null);
return cursorloader;
default:
break;
}

return cursorloader;
}[/syntax]
Так более корректно или опять не то :)?

Ну и если не надоел, вопрос насчет id :). При помощи id я погу получить 2 разных курсора ?
Например, мне нужно, чтоб один курсор загружал данные в какой-то listView в Activity, а другой курсор мог передать данные в какой-то диалог ?
Если да, то как определяется кому и какой Cursor передавать ? В onLoadFinished получить id loader'a ?
Спасибо.

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 05 ноя 2013, 21:15
Foenix
немного не поняла, что ты спрашиваешь, но у лоадера есть метод getId(), по нему можно определить какой именно лоадер используется. Подойдет?

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 05 ноя 2013, 21:46
Elek
Мне, например нужно иметь 2 курсора, с разными данными.
Как правильно вытащить из них данные ?
Сделать в onLoadFinished проверку по loader.getId() и в соовтетствии с этим уже обновлять нужный адаптер ?

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 06 ноя 2013, 10:30
Foenix
ну вообще-то так и делают, правильно.

Re: Вопрос по работе с LoaderManager.LoaderCallbacks<Cursor>

Добавлено: 06 ноя 2013, 22:25
Elek
Большое спасибо, за помощь :) !