2011-12-16 12 views
12

W mojej aplikacji na Androida używam SQLiteOpenHelper do implementacji ContentProvider. Kwerendy, dodawanie, usuwanie operacji odbywa się przez ContentProvider.Kiedy należy wywołać metodę close() na SQLiteOpenHelper używanym przez ContentProvider

Ale w jednym z moich telefonów z Androidem (htc g13) znalazłem plik * .db-wal w katalogu/data/data/[nazwa pakietu]/bazy danych. Rozmiar pliku rośnie bardzo szybko podczas pracy z ContentProvider. Za dużo zajmował przestrzeń RAM użytkownika.

Zaleca się zamknięcie SQLiteOpenHelper w celu rozwiązania mojego problemu (jest to przydatne) w poście enter link description here.

Ale chcę znaleźć "miejsce", aby dodać metodę "close()", ponieważ nie używam bezpośrednio SQLiteOpenHelper (używając ContentProvider). Metoda query() w ContentProvider musi zwrócić kursor, a SQLiteDatabse powinno pozostać w stanie otwartym.

Jestem zdezorientowany, co mam teraz zrobić, aby zachować * .db-wal i używać ContentProvider normalnie?

+2

To stary wątek, ale nadal istotny w Google, więc tutaj jest odniesienie do poprawnej odpowiedzi: http: // stackoverflow.com/questions/4547461/closing-the-database-in-a-contentprovider – saulobrito

+0

Myślę, że to najlepsza odpowiedź, dziękuję. – cmoaciopm

+0

Przeczytaj to świetne Objaśnienie i nie ma potrzeby zamykania bazy danych podczas korzystania z usługi contentProvider. Http://stackoverflow.com/questions/14002022/android-sq-lite-closed-exception/25379071#25379071 – Nepster

Odpowiedz

5

masz kilka przypadków na pokrycie:

1) Gdy kończy aplikację (np wprowadzając onDestroy()) upewnij się zamknąć wszystkie kursory, instancje bazy danych SQLiteDatabase i SQLiteOpenHelpers (stosując model (połączenie .isOpen()) object.close())

2) Gdy aplikacja jest uruchomionaPause() -> onResume() - użyj tego etapu odpowiednio, aby wstrzymać/wznowić połączenie lub zamknąć/otworzyć je.

Zaleca się zamknięcie bazy danych natychmiast po zakończeniu pracy z nią. Baza danych jest buforowane, więc nie ma problemu zamykania i ponownego nabycia instancji ponownie, gdy jest to potrzebne ze getWritableDatabase()/getReadableDatabase()

Od oficjalnego dokumentu: „Po otwarciu powodzeniem, baza danych jest buforowane, więc możesz wywołać tę metodę za każdym razem, gdy potrzebujesz zapisu do bazy danych. (Pamiętaj, aby wywołać metodę close(), gdy już nie potrzebujesz bazy danych). "

Pamiętaj też, że jeśli SQLiteOpenHelper buforuje i śledzi wszystko otwarte wystąpienia SQLiteDatabase, oznacza to, że jeśli nie zostawisz otwartych połączeń z bazami danych, nie będziesz musiał wywoływać zamknięcia w SQLiteOpenHelper.

Polecam zamknięcie wszystkich kursorów i baz danych natychmiast po zakończeniu pracy z nimi. Zawsze staraj się wymuszać operacje try/catch/dla zapytań, a na końcu blokować wywoływanie metod close na obiektach.

+0

Dzięki hovanessyan! Ale kłopotliwe jest to, że moja aplikacja obsługuje wiele wątków, nie wiem "kiedy" baza danych naprawdę nie jest potrzebna dla aplikacji. Drugi problem to: czym stoję przed ContentProvider (może ContentResolver będzie dokładny), z punktu projektowania warstwy, nie mogę uzyskać odniesienia SQLiteDatabase lub SQLiteOpenHelpers easilly. Nienawidzę koncepcji ContenProvider! – cmoaciopm

+0

jeśli używasz oddzielnych wątków dla wywołań DB, zakładam, że będziesz używać AsyncTasks. Jeśli tak jest, robisz wszystkie operacje w doInBackground() i zamykasz obiekty w onPostExecute(). Nie mogłem zrozumieć innego problemu. Czy możesz rozwinąć ten punkt projektowania warstwy? – hovanessyan

+1

Próbowałem logiki jak Twoja sugestia, ale dostałem wyjątek jak "baza danych już zamknięta". Myślę, że kod wykonuje seq jak poniżej: 1. wątek A getWritableDatabase(); 2. zamknij bazę danych wątku B; 3. wątek Wykonanie kwerendy sql i wyjątek się stało! – cmoaciopm

6

Inżynier systemów Android odracza ten widok, aby zamknąć bazę danych.

Zgodnie Dianne Hackborn (Android Framework Engineer) in this thread:

Dostawca treści jest tworzony, gdy proces jej gospodarzem jest tworzony i pozostaje około tak długo, jak proces ma, więc nie ma potrzeby do zamknij bazę danych - zostanie zamknięty jako część jądra , czyszcząc zasoby procesu po zabiciu procesu.

Powiązane problemy