Ошибка доступа к базе данных комнат с использованием RxJava, с использованием вариантов использования и чистой архитектуры - PullRequest
0 голосов
/ 29 января 2019

Я создаю приложение, используя чистую архитектуру.Я получаю сообщение об ошибке при вызове варианта использования из моей ViewModel, который должен выполнить запрос к моей базе данных комнат, сообщая, что я обращаюсь к нему в главном потоке.

Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
    at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204)
    at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:232)
    at com.something.data.db.PatientDAO_Impl.getAllPatients(PatientDAO_Impl.java:229)
    at com.something.data.repositories.dataSource.PatientDataStoreFactory.create(PatientDataStoreFactory.kt:18)
    at com.something.data.repositories.PatientRepositoryImplementation.getPatient(PatientRepositoryImplementation.kt:97)
    at com.something.domain.useCases.GetPatientUseCase.execute(GetPatientUseCase.kt:10)
    at com.something.some_thing.searchForm.SearchFormViewModel.getPatientFromDb(SearchFormViewModel.kt:49)
    at com.something.some_thing.searchForm.SearchFormFragment.onCreateView(SearchFormFragment.kt:99)
    at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
    at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
    at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
    at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1334)
    at android.app.Activity.performStart(Activity.java:7057)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2819)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931) 
    at android.app.ActivityThread.-wrap11(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620) 
    at android.os.Handler.dispatchMessage(Handler.java:105) 
    at android.os.Looper.loop(Looper.java:173) 
    at android.app.ActivityThread.main(ActivityThread.java:6698) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) 

Вот некоторый код

Мой вызов ViewModel:

fun getPatient(){
    val disposable = getPatientUseCase.execute()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::getPatientSuccess, this::onError)
    compositeDisposable.add(disposable)
}

Мой вариант использования:

class GetPatientUseCase(private val patientRepository: PatientRepository){

fun execute(): Single<Patient> {
    return patientRepository.getPatient()
}

Реализация метода моего репозитория

override fun getPatient(): Single<Patient> {
    val patientDataStore = PatientDataStoreFactory().create()
    return patientDataStore.patient()
}

Вот где происходит сбой в My PatientDataStoreFactory при запуске db.patientDAO (). GetAllPatients (). IsNotEmpty ():

@Singleton
class PatientDataStoreFactory {

    private val db = DaggerWrapper.getInstance().database()

    fun create(): PatientDataStore {

        return if (db.patientDAO().getAllPatients().isNotEmpty()){
            LocalPatientDataStore()
        } else {
            CloudPatientDataStore()
        }
    }
}

В моей ViewModel яподписка на исполнение сценария использования, поэтому я не понимаю эту аварию ... Есть идеи?

1 Ответ

0 голосов
/ 29 января 2019

Проблема здесь: db.patientDAO().getAllPatients().Вы звоните getAllPatients() в потоке пользовательского интерфейса.Вы должны заключить в Single и подписаться на Schedulers.io().

. Одним из возможных решений является переписать следующий код:

val patientDataStore = PatientDataStoreFactory().create()
return patientDataStore.patient()

примерно так:

return Single.fromCallable { PatientDataStoreFactory().create() }
             .flatMap { store -> store.patient() }
...