Użycie CursorLoader bez ContentProvider
Dokumentacja Android SDK mówi, że metoda startManagingCursor()
jest przestarzała:
Ta metoda jest przestarzała. Zamiast tego użyj nowej klasy CursorLoader z LoaderManager; jest ona również dostępna na starszych platformach za pośrednictwem pakietu kompatybilności z Androidem. Ta metoda pozwala aktywności zająć się zarządzaniem cyklem życia danego kursora w oparciu o cykl życia aktywności. Oznacza to, że gdy aktywność zostanie zatrzymana, automatycznie wywoła deactivate () na podanym kursorze, a po późniejszym ponownym uruchomieniu wywoła requery () dla Ciebie. Gdy aktywność zostanie zniszczona, wszystkie zarządzane Kursory zostaną automatycznie zamknięte. Jeśli celujesz w HONEYCOMB lub później, rozważ zamiast tego użycie LoaderManager, dostępnego za pomocą getLoaderManager ()
Więc chciałbym użyć CursorLoader
. Ale jak mogę go używać z custom CursorAdapter
i bez ContentProvider
, Kiedy potrzebuję URI w konstruktorze CursorLoader
?
5 answers
Napisałem prosty CursorLoader , który nie potrzebuje dostawcy treści:
import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;
/**
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above, this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*
* This was based on the CursorLoader class
*/
public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
private Cursor mCursor;
public SimpleCursorLoader(Context context) {
super(context);
}
/* Runs on a worker thread */
@Override
public abstract Cursor loadInBackground();
/* 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();
}
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
* <p/>
* Must be called from the UI thread
*/
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
}
Potrzebuje tylko klasy AsyncTaskLoader
. Albo ten w Androidzie 3.0 lub nowszym, albo ten, który jest dostarczany z pakietem kompatybilności.
Ja też napisałam ListLoader
który jest kompatybilny z LoadManager
i służy do pobierania ogólnej kolekcji java.util.List
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-22 18:38:02
Napisz własny loader, który używa twojej klasy bazy danych zamiast dostawcy treści. Najprostszym sposobem jest pobranie źródła klasy CursorLoader
z biblioteki kompatybilności i zastąpienie zapytań dostawcy zapytaniami do własnej klasy pomocniczej db.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-25 02:54:07
SimpleCursorLoader jest prostym rozwiązaniem, jednak nie obsługuje aktualizacji ładowarki, gdy dane ulegną zmianie. CommonsWare ma bibliotekę loaderex, która dodaje SQLiteCursorLoader i obsługuje ponowne Zapytanie o zmiany danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-22 17:58:51
Trzecią opcją byłoby po prostu nadpisanie loadInBackground
:
public class CustomCursorLoader extends CursorLoader {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
@Override
public Cursor loadInBackground() {
Cursor cursor = ... // get your cursor from wherever you like
if (cursor != null) {
// Ensure the cursor window is filled
cursor.getCount();
cursor.registerContentObserver(mObserver);
}
return cursor;
}
};
To również zajmie się ponownym zapytaniem kursora po zmianie bazy danych.
Tylko zastrzeżenie: będziesz musiał zdefiniować innego obserwatora, ponieważ Google w swojej nieskończonej mądrości postanowił uczynić swój pakiet prywatnym. Jeśli umieścisz klasę w tym samym pakiecie co oryginalna (lub compat), możesz użyć oryginalnej observer. Obserwator jest bardzo lekkim obiektem i nie jest używany nigdzie indziej, więc to nie robi wielkiej różnicy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-28 18:24:11
Trzecia opcja zaproponowana przez Timo Ohra, wraz z uwagami Yeunga, daje najprostszą odpowiedź (brzytwa Occama). Poniżej znajduje się przykład kompletnej klasy, która działa dla mnie. Istnieją dwie zasady korzystania z tej klasy.
- Rozszerz tę klasę abstrakcyjną i zaimplementuj metody getCursor () i getContentUri ().
-
Za każdym razem, gdy bazowa baza danych ulegnie zmianie (np. po wstawieniu lub usunięciu), upewnij się, że wywołujesz
getContentResolver().notifyChange(myUri, null);
Gdzie myUri jest tym samym zwracane z implementacji metody getContentUri ().
Oto kod dla klasy, której użyłem:
package com.example.project;
import android.content.Context;
import android.database.Cursor;
import android.content.CursorLoader;
import android.content.Loader;
public abstract class AbstractCustomCursorLoader extends CursorLoader
{
private final Loader.ForceLoadContentObserver mObserver = new Loader.ForceLoadContentObserver();
public AbstractCustomCursorLoader(Context context)
{
super(context);
}
@Override
public Cursor loadInBackground()
{
Cursor cursor = getCursor();
if (cursor != null)
{
// Ensure the cursor window is filled
cursor.getCount();
cursor.registerContentObserver(mObserver);
}
cursor.setNotificationUri(getContext().getContentResolver(), getContentUri());
return cursor;
}
protected abstract Cursor getCursor();
protected abstract Uri getContentUri();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 23:20:36