首页 > 解决方案 > 为什么 Room 不创建数据库?

问题描述

我正在为我的项目使用房间,但我无法创建房间数据库。

你能告诉我我做错了什么吗?

谢谢!

我有一个名为Appointment.

@Entity
public class Appointment {
    @PrimaryKey
    @NonNull
    private final UUID uuid;
    private String title;
    private String description;

    public Appointment(UUID uuid, String title, String description) {
        this.uuid = uuid;
        this.title = title;
        this.description = description;
    }

我已经实现了一个名为AppointmentDAO

@Dao
public interface AppointmentDAO {
    @Transaction
    @Query("SELECT * FROM Appointment")
    public List<Appointment> getAppointments();

    @Transaction
    @Query("SELECT * FROM Appointment WHERE uuid = :uuid")
    public List<Appointment> getAppointmentByUUID(UUID uuid);

    @Insert
    void insertAppointment(Appointment appointment);

    @Update
    void updateAppointment(Appointment appointment);

    @Delete
    void deleteAppointment(Appointment appointment);

    @Query("SELECT * FROM Appointment")
    Single<List<Appointment>> getAppointmentsAsyncOneShot();

    @Query("SELECT * FROM Appointment WHERE uuid = :uuid")
    Single<Appointment> getAppointmentByUUIDAsyncOneShot(UUID uuid);

    @Insert
    Completable insertAppointmentAsyncOneShot(Appointment appointment);

    @Update
    Completable updateAppointmentAsyncOneShot(Appointment appointment);

    @Delete
    Completable deleteAppointmentAsyncOneShot(Appointment appointment);

    @Query("SELECT * FROM Appointment")
    Flowable<Appointment> getAppointmentsAsyncObservable();

    @Query("SELECT * FROM Appointment WHERE uuid = :uuid")
    Flowable<Appointment> getAppointmentByUUIDAsyncObservable(UUID uuid);

}

我还创建了一个AppDatabase抽象类:

@Database(entities = {
        Appointment.class
}, version = 1)
@TypeConverters({
        UUIDConverter.class
})
public abstract class AppDatabase extends RoomDatabase {
    private static final String TAG = "AppDatabase";

    private static final String DB_NAME = "XXXYYYYYYYYYYDatabase.db";

    private static AppDatabase instance;

    protected AppDatabase() {}

    public static synchronized AppDatabase getInstance(Context context) {
        if (instance == null) {
            instance = create(context);
        }
        return instance;
    }

    private static AppDatabase create(final Context context) {
        Log.d(TAG, "create() called with: context = [" + context + "]");
        return Room
                .databaseBuilder(context.getApplicationContext(), AppDatabase.class, DB_NAME)
                .build();
    }

    public abstract AppointmentDAO getAppointmentDAO();
}

我在一个片段中调用这个方法,它异步插入一个Appointment

private void addAppointmentToDatabase() {
        AppDatabase
                .getInstance(requireContext())
                .getAppointmentDAO()
                .insertAppointmentAsyncOneShot(viewModel.getAppointment().getValue())
                .subscribe(new DisposableCompletableObserver() {
                    @Override
                    public void onComplete() {
                        Toast.makeText(requireContext(), "YES", Toast.LENGTH_LONG)
                                .show();
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Toast.makeText(requireContext(), "NO", Toast.LENGTH_LONG)
                                .show();
                    }
                });
    }

build.gradle(应用程序):

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 29
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.xxxxxxxx"
        minSdkVersion 22
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    buildFeatures {
        dataBinding true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    testImplementation 'junit:junit:4.13.1'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'


    def nav_version = "2.3.2"

    // Java language implementation
    implementation "androidx.navigation:navigation-fragment:$nav_version"
    implementation "androidx.navigation:navigation-ui:$nav_version"

    // Feature module Support
    implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

    // Testing Navigation
    androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

    // Jetpack Compose Integration
    implementation "androidx.navigation:navigation-compose:1.0.0-alpha04"


    implementation 'com.google.android.gms:play-services-location:17.1.0'


    def room_version = "2.2.6"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // optional - RxJava support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"
}

我没有错误,也没有数据库:(。

标签: androiddatabaseandroid-room

解决方案


啊 - 你没有正确使用 rxJava。简单明了,您不能在主 UI 线程上进行数据库调用。Room 要求在单独的线程中调用它们。rxJava 增加了一定程度的复杂性,使得一开始很难调试。我建议使用 Runnable 或 Executors 类创建一个非常简单的线程,并在其中调用 db 函数。一旦您可以确认您的数据库逻辑正在工作,那么您可以继续实现 rxJava。

编辑:我不是 rxJava 的专业人士,但我确实相信您缺少设置要在哪个线程上运行的功能(AndroidSchedulers.io)或类似的东西,我不记得了。

可运行的示例:

 private void addAppointmentToDatabase(Appointment appointment) {
    new Runnable() {

        @Override
        public void run() {
            AppDatabase
                    .getInstance(requireContext())
                    .getAppointmentDAO()
                    .insertAppointment(appointment);
        }
    };
}

关于 Android 线程


推荐阅读