带有两个数据库“表”,“外键”和“实时数据”的房间

时间:2018-10-20 09:54:03

标签: android android-room android-livedata android-jetpack

尝试创建具有两个相关表一对一的会议室数据库。通过外键进行连接,但是我发现用实时数据获取数据很困难,我不知道这种获取数据是否正确。

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
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更改值,实时数据接收onChange和观察者。我想知道有什么方法可以解决此问题,因此我可以在分配任务时使用livedata从会议室数据库接收值。

@PS发现了问题。当我尝试在Observer {...}中获取DataFiles时,它不起作用,但是当我从onCreateView {...}中调用函数时,它起作用了。 有解决办法吗?

1 个答案:

答案 0 :(得分:0)

这里的主要问题是您需要观察并更新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)
    }
}