Pokoje umożliwiają konwersję między typami podstawowymi i pudełkowymi , ale nie zezwala na odwołania do obiektów między elementami. Ten dokument Wyjaśnia, jak używać konwerterów typów i dlaczego pokój nie obsługuje obiektu odwołania.
Używanie konwerterów typów
Czasami aplikacja musi przechowywać niestandardowy typ danych w pojedynczej bazie danych.
. Obsługujesz typy niestandardowe, udostępniając tagi konwersji typu, które są
instruujących Room konwertowanie typów niestandardowych na i ze znanych typów,
Pomieszczenie może być nieodwracalne. Konwertery typu możesz określić za pomocą
@TypeConverter
.
Załóżmy, że chcesz zachować wystąpienia ciągu Date
w
do bazy danych sal. W pokoju nie wiadomo, jak utrwalić Date
obiekty, dlatego potrzebujesz
aby zdefiniować konwertery typów:
Kotlin
class Converters { @TypeConverter fun fromTimestamp(value: Long?): Date? { return value?.let { Date(it) } } @TypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time?.toLong() } }
Java
public class Converters { @TypeConverter public static Date fromTimestamp(Long value) { return value == null ? null : new Date(value); } @TypeConverter public static Long dateToTimestamp(Date date) { return date == null ? null : date.getTime(); } }
W tym przykładzie zdefiniowano 2 metody konwertera typu: jedną, która konwertuje: Date
do obiektu Long
i drugiego, który wykonuje odwrotną konwersję z obiektu
Long
do Date
. Pokój wie, jak zachować obiekty Long
, więc może użyć
aby zachować Date
obiektów.
Następnie dodaj @TypeConverters
adnotacja do klasy AppDatabase
, dzięki której pokój wie o konwertocie
zdefiniowaną klasę:
Kotlin
@Database(entities = [User::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) @TypeConverters({Converters.class}) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
Po zdefiniowaniu konwerterów typu niestandardowego możesz użyć typu niestandardowego w encje i DAO w taki sam sposób jak w przypadku typów podstawowych:
Kotlin
@Entity data class User(private val birthday: Date?) @Dao interface UserDao { @Query("SELECT * FROM user WHERE birthday = :targetDate") fun findUsersBornOnDate(targetDate: Date): List<User> }
Java
@Entity public class User { private Date birthday; } @Dao public interface UserDao { @Query("SELECT * FROM user WHERE birthday = :targetDate") List<User> findUsersBornOnDate(Date targetDate); }
W tym przykładzie Sala może wszędzie używać konwertera zdefiniowanego typu, ponieważ
dodał adnotacje AppDatabase
z @TypeConverters
. Możesz też wybrać typ
użytkowników, którzy dokonali konwersji w konkretne jednostki lub użytkowników DAO, dodając adnotacje do @Entity
lub @Dao
zajęcia z @TypeConverters
.
Inicjowanie konwertera typu elementu sterującego
Zazwyczaj usługa Sala obsługuje wystąpienia konwerterów typu za Ciebie. Pamiętaj jednak:
czasami konieczne może być przekazanie dodatkowych zależności do konwertera typów
klas, co oznacza, że aplikacja musi bezpośrednio kontrolować inicjowanie.
konwerterów danego typu. W takim przypadku dodaj do klasy konwertera adnotację
@ProvidedTypeConverter
:
Kotlin
@ProvidedTypeConverter class ExampleConverter { @TypeConverter fun StringToExample(string: String?): ExampleType? { ... } @TypeConverter fun ExampleToString(example: ExampleType?): String? { ... } }
Java
@ProvidedTypeConverter public class ExampleConverter { @TypeConverter public Example StringToExample(String string) { ... } @TypeConverter public String ExampleToString(Example example) { ... } }
Oprócz zadeklarowania klasy konwersji w tym języku (@TypeConverters
) możesz użyć funkcji
RoomDatabase.Builder.addTypeConverter()
.
aby przekazać instancję klasy konwertera do funkcji RoomDatabase
kreator:
Kotlin
val db = Room.databaseBuilder(...) .addTypeConverter(exampleConverterInstance) .build()
Java
AppDatabase db = Room.databaseBuilder(...) .addTypeConverter(exampleConverterInstance) .build();
Wyjaśnienie, dlaczego sala nie zezwala na odwołania do obiektów
Podsumowanie: Sala nie zezwala na odwołania do obiektów między klasami encji. Zamiast tego musisz: wyraźnie żądać danych, których potrzebuje aplikacja.
Mapowanie relacji z bazy danych do odpowiedniego modelu obiektu jest powszechne i świetnie działa po stronie serwera. Nawet po wczytaniu programu z wykorzystaniem różnych pól, serwer nadal działa dobrze.
Po stronie klienta ten typ leniwego ładowania jest jednak niemożliwy, ponieważ zwykle występuje w wątku UI i wysyła zapytania o informacje na dysku w interfejsie użytkownika. powoduje poważne problemy z wydajnością. Wątek UI zwykle ma ok. 16 ms na obliczenie i rysowanie zaktualizowanego układu aktywności, więc nawet jeśli trwa tylko 5 ms, prawdopodobnie aplikacja zabraknie czasu narysować ramkę, co powoduje zauważalne problemy wizualne. Zapytanie może zająć nawet mieć więcej czasu na realizację, jeśli równolegle odbywa się inna transakcja. gdy urządzenie jest uruchomione inne zadania wymagające dużej ilości dysku. Jeśli nie używasz leniwego ale aplikacja pobiera więcej danych, niż jest potrzebna, dlatego tworzy pamięć. problemów z konsumpcją treści.
W przypadku mapowań obiektów i relacji obiektów decyzyjnych te decyzje zwykle podejmują deweloperzy, więc mogą zrobić wszystko, co jest najlepsze w danym przypadku. Zwykle deweloperzy zdecydować się na współdzielenie modelu między aplikacją a UI. To rozwiązanie: można dobrze skalować, ponieważ wraz z upływem czasu interfejs zmienia się, tworzy problemy, które są trudne do przewidzenia i debugowania przez programistów.
Weźmy na przykład interfejs, który wczytuje listę obiektów Book
z każdą książką
ma obiekt Author
. Możesz początkowo projektować zapytania tak, aby używać
wczytuję, aby instancje Book
pobrały autora. Pierwsze pobranie wartości
pole author
wysyła zapytanie do bazy danych. Po jakimś czasie zdajesz sobie sprawę,
musisz też wyświetlać imię i nazwisko autora w interfejsie aplikacji. Masz dostęp do:
Jak widać w tym fragmencie kodu:
Kotlin
authorNameTextView.text = book.author.name
Java
authorNameTextView.setText(book.getAuthor().getName());
Jednak ta pozornie niewinna zmiana powoduje, że dane w tabeli Author
pojawiają się w wynikach wyszukiwania.
w wątku głównym.
Jeśli zapytasz o autora z wyprzedzeniem, trudno będzie zmienić
jak dane są wczytywane, gdy już ich nie potrzebujesz. Na przykład, jeśli aplikacja
Interfejs nie musi już wyświetlać informacji o aplikacji Author
– aplikacja się wczytuje
danych, których już nie wyświetla, i tym samym marnuje cenne miejsce w pamięci. W przypadku Twojej aplikacji
wydajność spada jeszcze bardziej, jeśli klasa Author
odwołuje się do innej tabeli,
na przykład Books
.
Aby odwoływać się do wielu elementów jednocześnie za pomocą Pokoju, utwórz zamiast tego plik funkcja POJO, która obejmuje każdą encję, a następnie napisz zapytanie, które łączy odpowiednie tabeli. Ten dobrze uporządkowany model w połączeniu z rozbudowanym zapytaniem pokoju umożliwia aplikacji zużywanie mniejszej ilości zasobów podczas wczytywania danych, zwiększając wydajność aplikacji i wrażenia użytkowników.