Комната с двумя таблицами базы данных, внешним ключом и живыми данными - PullRequest
0 голосов
/ 20 октября 2018

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

class GraphFragment : Fragment() {

   private lateinit var graphVM: GraphVM

   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_graph, container, false)
        graphVM = ViewModelProviders.of(this).get(GraphVM::class.java)

        graphVM.graphFiles.observe(this, Observer<List<GraphEntity>> {
            it?.let {
                graphVM.getDataFiles( it.map { it.fileID })
            }
        })

        graphVM.dataFiles.observe(this, Observer<List<FileEntity>> {
            it?.let {
                // work with FileEntity
            }
        })
}

Viewmodel

class GraphVM(application: Application) : AndroidViewModel(application) {

        private var graphFilesRepository: GraphRepository = GraphRepository(application)
        private var fileRepository: FileRepository = FileRepository(application)

        var graphFiles: LiveData<List<GraphEntity>> = MutableLiveData()
            private set

        var dataFiles: LiveData<List<FileEntity>> = MutableLiveData()
            private set

        init {
            // this work
            graphFiles = graphFilesRepository.getAllFiles()
        }

        fun getDataFiles(listOfFileIDs: List<Long?>) {
            // this not
            dataFiles = fileRepository.getFilesDataByID(listOfFileIDs)
        }
    }

FileRepository

class FileRepository(application: Application) {
    private var fileDao: FileDao

    init {
        val database: FileDatabase = FileDatabase.getInstance(application)!!
        fileDao = database.fileDao()
    }

    /..
    ../


    fun getFilesDataByID(listOfFileIDs: List<Long?>): LiveData<List<FileEntity>> {
        return fileDao.queryFilesEntityByID(listOfFileIDs)
    }
}

Dao

@Dao
interface FileDao {

    /..
    ../

    @Query("SELECT * FROM file_data WHERE id IN (:listOfFileIDs)")
    fun queryFilesEntityByID(listOfFileIDs : List<Long?>): LiveData<List<FileEntity>>
}

Итак, когда у меня есть назначение в init, живые данные запускаются правильно, но когда я пытаюсь:

graphVM.getDataFiles( it.map { it.fileID })

Livedata - это назначение, но не срабатывание.Я знаю, что это присваивание правильно, потому что когда я удаляю, изменяю значения из FileRepository, aliveata recive onChange и наблюдатель информируется.Я хотел бы знать, есть ли способ исправить это, поэтому я могу использовать liveata для получения значений из базы данных комнат во время назначений.

@ PS обнаружил проблему.Когда я пытаюсь получить getDataFiles в Observer {...}, это не работает, но когда я вызываю функцию из onCreateView {...}, это работает.Любое решение?

1 Ответ

0 голосов
/ 22 октября 2018

Основная проблема здесь заключается в том, что вам нужно наблюдать и обновлять один экземпляр LiveData, но вызов getDataFiles() переопределить dataFiles поле.

Предпочтительное решение - предоставить запрос LiveData клиенту и наблюдайте за обновлениями на стороне клиента:

class GraphVM(application: Application) : AndroidViewModel(application) {

    //...

    fun getDataFiles(listOfFileIDs: List<Long?>): LiveData<List<FileEntity>> {
        return fileRepository.getFilesDataByID(listOfFileIDs)
    }
}

Если этот подход не подходит, вы можете использовать MediatorLiveData для переключения источников данных:

class GraphVM(application: Application) : AndroidViewModel(application) {

    private var fileRepository: FileRepository = FileRepository(application)

    private val dataFiles = MediatorLiveData<List<FileEntity>>()
    private var request: LiveData<List<FileEntity>>? = null

    // expose dataFiles as LiveData
    fun getDataFiles(): LiveData<List<FileEntity>> = dataFiles

    @MainThread
    fun getDataFiles(listOfFileIDs: List<Long?>) {
        // create new request to repository
        val newRequest = fileRepository.getFilesDataByID(listOfFileIDs)
        val observer = Observer<List<FileEntity>> { list ->
            // remove previous subscription
            request?.run { dataFiles.removeSource(this) }
            // setup fresh data
            dataFiles.value = list
            // remember last request
            request = newRequest
        }
        // register new observable data source (LiveData)
        dataFiles.addSource(newRequest, observer)
    }
}
...