Dokumentacja Android SDK mówi, że startManagingCursor()
metoda jest pozbawiona wartości:
Ta metoda jest przestarzała. Zamiast tego użyj nowej klasy CursorLoader z LoaderManager; jest to również dostępne na starszych platformach za pośrednictwem pakietu zgodności z systemem Android. Ta metoda pozwala aktywności zająć się zarządzaniem cyklem życia danego kursora w oparciu o cykl życia działania. Oznacza to, że gdy aktywność zostanie zatrzymana, automatycznie wywoła dezaktywację () na danym kursorze, a po późniejszym ponownym uruchomieniu wywoła dla Ciebie requery (). Gdy aktywność zostanie zniszczona, wszystkie zarządzane kursory zostaną automatycznie zamknięte. Jeśli celujesz w HONEYCOMB lub nowszy, zamiast tego rozważ użycie LoaderManager, dostępnego przez getLoaderManager ()
Więc chciałbym użyć CursorLoader
. Ale jak mogę go używać z niestandardowym CursorAdapter
i bez ContentProvider
, kiedy potrzebuję URI w konstruktorze CursorLoader
?
Odpowiedzi:
Napisałem prosty CursorLoader , który nie potrzebuje dostawcy treści:
Potrzebuje tylko
AsyncTaskLoader
klasy. Albo ten w systemie Android 3.0 lub nowszym, albo ten, który jest dostarczany z pakietem zgodności.Ja też napisałem
ListLoader
, która jest zgodna zLoadManager
i jest używany do pobierania rodzajowejava.util.List
kolekcji.źródło
Napisz własny moduł ładujący, który używa Twojej klasy bazy danych zamiast dostawcy treści. Najprostszym sposobem jest po prostu pobranie źródła
CursorLoader
klasy z biblioteki zgodności i zastąpienie zapytań dostawców zapytaniami do własnej klasy pomocniczej db.źródło
CursorLoader
descendat do zarządzania kursorem SQLite, poza konstruktorem potrzebowałem tylko przesłonićloadInBackground
metodę, aby zastąpić zapytanie dostawcy moim zapytaniem kursoraSimpleCursorLoader jest prostym rozwiązaniem, jednak nie obsługuje aktualizowania modułu ładującego w przypadku zmiany danych. CommonsWare ma bibliotekę loaderex, która dodaje SQLiteCursorLoader i obsługuje ponowne zapytania dotyczące zmian danych.
https://github.com/commonsguy/cwac-loaderex
źródło
Trzecią opcją byłoby po prostu zastąpienie
loadInBackground
:Spowoduje to również ponowne wysłanie zapytania do kursora po zmianie bazy danych.
Jedyne zastrzeżenie: musisz zdefiniować innego obserwatora, ponieważ Google w swojej nieskończonej mądrości zdecydował, że ich pakiet będzie prywatny. Jeśli umieścisz klasę w tym samym pakiecie, co oryginalna (lub zgodna), możesz faktycznie użyć oryginalnego obserwatora. Obserwator jest bardzo lekkim obiektem i nie jest używany nigdzie indziej, więc nie robi to dużej różnicy.
źródło
loadInBackground()
, przed zwróceniem kursora, powiedz, żecursor.setNotificationUri(getContext().getContentResolver(), uri);
uri może pochodzić z losowego ciągu, takiego jakUri.parse("content://query_slot1")
. Wygląda na to, że nie obchodzi go, czy uri naprawdę istnieje, czy nie. A kiedy zrobiłem operację na DB. SaygetContentResolver().notifyChange(uri, null);
załatwi sprawę. Następnie mogę utworzyć kilka "slotów zapytań uri" w stałym pliku dla aplikacji z niewielką liczbą zapytań. Testuję wstawianie rekordu DB w czasie wykonywania i wydaje się, że działa, ale nadal wątpię, czy jest to dobra praktyka onit. Jakieś sugestie?Trzecia opcja zaproponowana przez Timo Ochra, wraz z komentarzami Yeunga, dają najprostszą odpowiedź (brzytwa Ockhama). Poniżej znajduje się przykład kompletnej klasy, która działa dla mnie. Istnieją dwie zasady korzystania z tej klasy.
Za każdym razem, gdy podstawowa baza danych ulegnie zmianie (np. Po wstawieniu lub usunięciu), należy wywołać
gdzie myUri to ta sama wartość, która została zwrócona przez implementację metody getContentUri ().
Oto kod klasy, której użyłem:
źródło