Как узнать, что обратный вызов onCreate () Room завершен - PullRequest
0 голосов
/ 17 июня 2020

Я работаю над приложением, которое использует Room базу данных; это база данных stati c, в которой есть 3 таблицы, в которые я вставляю их данные при первом запуске приложения путем переопределения onCreate() при создании экземпляра базы данных.

Требуется некоторое время, чтобы вставить все данные c записи в три таблицы, поэтому мое приложение не может получить доступ к базе данных, пока не закончится onCreate(), чтобы вернуть нужные данные, которые будут показаны пользователю.

Когда я пытаюсь получить доступ к базе данных в пределах действия onCreate() метод, он возвращает null данные, и это буквально прерывает операцию onCreate комнаты, что приводит к нулевым данным для предстоящих запусков приложения, поскольку onCreate() комнаты вызывается только один раз.

В целях отладки, когда я избавляюсь от доступа к этой базе данных только при первом запуске приложения (после чистого удаления), чтобы позволить базе данных накапливаться для первого запуска; затем, когда я повторно добавляю запрос к базе данных в свою операцию onCreate() и перезапускаю приложение; возвращает ненулевые данные; Я просто хотел убедиться, что номер onCreate() в комнате закончился при первом запуске.

Я могу передать слушателя в настраиваемый класс RoomDatabase, где его обратный вызов может быть запущен по окончании метода onCreate(); но я не уверен, правильный ли это способ сделать это или есть другой элегантный способ, и правильный ли это путь; затем как правильно реализовать это с учетом шаблона проектирования MVVM, например, Repository, ViewModel.

Вот как выглядит класс базы данных

@Database(entities = {Table1.class, Table2.class, Table3.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {

    public static final String DATABASE_NAME = "database.db";
    private static volatile AppDatabase INSTANCE;
    private static final Object LOCK = new Object();

    public abstract Table1Dao getTable1Dao();
    public abstract Table2Dao getTable2Dao();
    public abstract Table2Dao getTable3Dao();

    private static Executor mExecutor = Executors.newSingleThreadExecutor();


    static public AppDatabase getInstance(final Context context) {
        if (INSTANCE == null) {
            synchronized (LOCK) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, DATABASE_NAME)
                            .addCallback(new Callback() {
                                @Override
                                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                                    mExecutor.execute(() -> table1InsertOperation(context));
                                    mExecutor.execute(() -> table2InsertOperation(context));
                                    mExecutor.execute(() -> table3InsertOperation(context));
                                   super.onCreate(db);
                                }
                            })
                            .build();
                }
            }
        }
        return INSTANCE;
    }

}

Оцените ваша помощь

Ответы [ 2 ]

1 голос
/ 18 июня 2020

«Когда я пытаюсь получить доступ к базе данных в методе onCreate () действия, он возвращает нулевые данные, и это буквально прерывает операцию onCreate Room, что приводит к нулевым данным для предстоящих запусков приложения в качестве onCreate () Room. вызывается только один раз ". Мне это кажется довольно странным, база данных создана, чтобы позволить нескольким потокам читать и писать, так почему это должно происходить?

«Я могу передать слушателя в настраиваемый класс RoomDatabase, где его обратный вызов может быть запущен после завершения метода onCreate ()» Я вижу, вы используете Executor для запуска фазы заполнения в фоновых потоках, поэтому onCreate должен завершиться sh почти сразу, потоки, заполняющие базу данных, скорее всего, намного позже. Вам нужно будет отслеживать, когда все три потока, которые вы запускаете, завершают sh свою работу. То же, что и слушатель, но намного проще (как только вы решите пункт 1, который кажется ошибкой где-то в вашем коде или, что менее вероятно, в комнате), будет просто иметь LiveData (или Flow), который сообщает вам, когда все строки вставлены.

Посмотрите на это репо: https://gist.github.com/florina-muntenescu/697e543652b03d3d2a06703f5d6b44b5 она использует Executors.newSingleThreadExecutor() и похоже на то, что вы делаете

Ps. Android В Studio 4.1 есть замечательный Инспектор баз данных, попробуйте!

0 голосов
/ 17 июня 2020

Используйте разрабатываемую версию вашего приложения или другого инструмента (например, sqlite3 ), чтобы создать файл базы данных, содержащий ваши фиксированные данные. Поместите файл БД в каталог assets/ вашего приложения и используйте его для предварительного заполнения базы данных .

Подробности см. В документации для createFromAsset () .

Предполагается, что получившаяся база данных приложения будет готова к использованию сразу после возврата из RoomDatabase.build () . Вы также можете использовать обратный вызов onOpen () .

...