Sfera nie ma już tego problemu.
Dla porównania moje rozwiązanie w tym czasie było:
Dzięki beeender dla wskazujące mnie we właściwym kierunku i łączenie tego PR https://github.com/realm/realm-java/pull/1297
Issue
Kiedy jest w toku transakcja Realm każde wywołanie Realm.getInstance
w innym wątku zostanie zablokowane do czasu zatwierdzenia lub anulowania oczekującej transakcji.
W moim przypadku mam IntentService, która wypełnia mój obszar istniejącymi danymi użytkownika, podczas gdy ja staram się wyświetlać wszelkie aktualne dane przez zapytanie Realm w wątku UI. Chociaż zapytania są proste i nie powodują problemów w normalny sposób, jeśli w IntentService trwa transakcja oczekująca, wywołanie Realm.getInstance
zostanie zablokowane, blokując wątek UI, potencjalnie powodując ANR.
Moja pierwsza próba rozwiązania polegała na przyciąganiu gałęzi PR-a i utworzeniu słoja. Wierzę, że ta poprawka doprowadziła mnie o krok dalej, umożliwiając utworzenie instancji Realm bez blokowania, ale wątek interfejsu użytkownika był nadal blokowany przez małe transakcje, które próbowałem wykonać w wątku UI.
Rozwiązanie
Rozwiązanie I wdrożone obejmuje kilka etapów:
- Tworzenie duplikatów obiektów dla wszystkich moich modeli. Duplikaty nie rozszerzają RealmObject (ponieważ RealmObjects nie mogą być używane w wątkach).
- Przenieś wszystkie dostępy do dziedziny na wątki w tle. Zasadniczo opakowałem moje zapytania w AsyncTasks i dodałem detektory, które zwracają wersję modelu inną niż RealmObject.
- Wykonuj więcej małych transakcji niż mniej dużych transakcji. Gdzie wcześniej zacząłem i zatwierdziłem transakcje po obu stronach pętli, która stworzyła wiele nowych obiektów RealmObject, teraz rozpoczynam i zatwierdzam transakcję na obiekt.Ma to na celu zmniejszenie całkowitego niezakłóconego czasu, w którym Realm może znajdować się w stanie otwartej transakcji, więc moje zapytania dostarczające dane do interfejsu użytkownika mogą zostać ukończone bez konieczności czekania tak długo.
Wnioski
Początkowo byłem niezdecydowany używać Realm powodu wciąż jest w fazie beta, a także zastrzeżenie, że RealmObjects nie może być stosowany w całej wątków. Po kilku testach czułam się pewna, że mogę bezbłędnie wykonywać proste zapytania w wątku UI (nadal z poczuciem winy w moim wnętrzu).
Ogólne królestwo to świetny projekt, który warto mieć na oku, ale czuję, że nie jest gotowy do dużych projektów komercyjnych. Korzystanie z Realm w tym projekcie mogło zaoszczędzić trochę czasu, ale kosztowało wielu niezadowolonych klientów i trudny do zdiagnozowania problem.
* Edycja: sklarowano problem.
Wygląda na to, że masz transakcję zapisu, która nie jest zamknięta. To może zablokować Królestwo, aby otworzyć nową instancję. Sprawdź to PR https://github.com/realm/realm-java/pull/1297. Jeśli tak jest, sugeruję, abyś zamknął transakcję poprawnie, zamiast czekać na naprawę, ponieważ transakcja zapisu i tak musi zostać zamknięta. – beeender
@beeender Więc jeśli rozpocznę transakcję w wątku roboczym i spróbuję otworzyć nową instancję Realm w wątku interfejsu użytkownika przed zatwierdzeniem transakcji wątku roboczego, wątek interfejsu użytkownika zostanie zablokowany w oczekiwaniu na zatwierdzenie transakcji? – MichaelAnDev
Teraz, tak. Chociaż nie sądzę, że jest to właściwe zachowanie, być może istnieją pewne przyczyny obecnego zachowania, którego nie jestem świadomy. Teraz, gdy utworzysz instancję Realm w jednym wątku i nie ma jeszcze otwartej instancji w wątku, zostanie wywołana funkcja createAndValidate, która może zostać zablokowana przez transakcję w innych wątkach. Ale jeśli istnieje już jedno otwarte wystąpienie w wątku, odniesienie zostanie zwrócone bez tworzenia. – beeender