Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/216.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何使用房间数据库实现多个查询?_Android_Android Studio_Android Room_Android Mvvm - Fatal编程技术网

Android 如何使用房间数据库实现多个查询?

Android 如何使用房间数据库实现多个查询?,android,android-studio,android-room,android-mvvm,Android,Android Studio,Android Room,Android Mvvm,我正在使用MVVM模式的room数据库创建一个android应用程序,问题是我在获取数据时不能使用多个查询。我可以提取一次数据,但是我不能再这样做了 DAO接口: @Dao interface StockDao { @Insert suspend fun insert(stock:Stock) @Update suspend fun update(stock:Stock) @Delete suspend fun delete(stock:St

我正在使用MVVM模式的room数据库创建一个android应用程序,问题是我在获取数据时不能使用多个查询。我可以提取一次数据,但是我不能再这样做了

DAO接口:

@Dao
interface StockDao {

    @Insert
    suspend fun insert(stock:Stock)

    @Update
    suspend fun update(stock:Stock)

    @Delete
    suspend fun delete(stock:Stock)

    @Query("DELETE FROM stock_table")
    suspend fun deleteAll()

    @Query("SELECT * FROM stock_table")
    fun selectAll():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table WHERE isFinished = 0")
    fun selectAllUnfinished(): Flow<List<Stock>>

    @Query("SELECT * FROM stock_table WHERE isFinished = 1")
    fun selectAllFinished():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table ORDER BY totalSpent DESC")
    fun selectAllOrderByDesc():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table ORDER BY totalSpent ASC")
    fun selectAllOrderByAsc():Flow<List<Stock>>

}
class StockRepository(private val stockDao: StockDao) {

    private lateinit var allStock: Flow<List<Stock>>


    suspend fun insert(stock: Stock) {

        stockDao.insert(stock)

    }

    suspend fun update(stock: Stock) {

        stockDao.update(stock)

    }

    suspend fun delete(stock: Stock) {

        stockDao.delete(stock)

    }

    suspend fun deleteAll() {

        stockDao.deleteAll()

    }

    fun selectAll(): Flow<List<Stock>> {

        allStock = stockDao.selectAll()

        return allStock

    }

    fun selectAllOrderByDesc(): Flow<List<Stock>> {

        allStock = stockDao.selectAllOrderByAsc()

        return allStock

    }

    fun selectAllOrderByAsc(): Flow<List<Stock>> {

        allStock = stockDao.selectAllOrderByAsc()

        return allStock

    }

    fun selectAllFinished(): Flow<List<Stock>> {

        allStock = stockDao.selectAllFinished()

        return allStock

    }

    fun selectAllUnfinished(): Flow<List<Stock>> {

        allStock = stockDao.selectAllUnfinished()

        return allStock

    }


}
class StockViewModel(private val repo: StockRepository) : ViewModel() {

    companion object {

        const val ALL = 0
        const val ORDER_BY_DESC = 1
        const val ORDER_BY_ASC = 2
        const val FINISHED = 3
        const val UNFINISHED = 4

    }

    var allStocks = repo.selectAll().asLiveData()


    fun insert(stock: Stock) = viewModelScope.launch {
        repo.insert(stock)
    }

    fun update(stock: Stock) = viewModelScope.launch {
        repo.update(stock)
    }

    fun delete(stock: Stock) = viewModelScope.launch {
        repo.delete(stock)
    }

    fun deleteAll() = viewModelScope.launch {
        repo.deleteAll()
    }

    fun selectAllStockWithFilter(filter: Int): LiveData<List<Stock>> {

        when (filter) {

            ALL -> allStocks = repo.selectAll().asLiveData()
            ORDER_BY_DESC -> allStocks = repo.selectAllOrderByDesc().asLiveData()
            ORDER_BY_ASC -> allStocks = repo.selectAllOrderByAsc().asLiveData()
            FINISHED -> allStocks = repo.selectAllFinished().asLiveData()
            UNFINISHED -> allStocks = repo.selectAllUnfinished().asLiveData()
        }

        return allStocks

    }


    class StockViewModelFactory(private val repo: StockRepository) : ViewModelProvider.Factory {

        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(StockViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return StockViewModel(repo) as T
            }

            throw IllegalArgumentException("Unknown viewModel class")
        }

    }


}
class FinanceApplication :Application(){

    private val database by lazy {  FinanceDatabase.getInstance(this)}

    val stockRepository by lazy { StockRepository(database.stockDao()) }
}


class StocksActivity : AppCompatActivity() {

    //Layout components
    private lateinit var binder: ActivityStocksBinding
    private lateinit var recyclerView: RecyclerView
    private lateinit var recyclerViewAdapter: StockAdapter

    //ViewModel
    private val viewModel: StockViewModel by viewModels {
        StockViewModel.StockViewModelFactory((application as FinanceApplication).stockRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binder = ActivityStocksBinding.inflate(layoutInflater)
        setContentView(binder.root)
    
        fetchStocks()


    }

    private fun fetchStocks() {


        viewModel.allStocks.observe(this) {

            recyclerViewAdapter.submitList(it)

        }


    }

    private fun initRecyclerViewLayout() {


        val recyclerViewLayoutBinder = binder.includedLayout

        recyclerView = recyclerViewLayoutBinder.stocksRecyclerView
        recyclerViewAdapter = StockAdapter(this)
        recyclerView.adapter = recyclerViewAdapter
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.setHasFixedSize(true)


    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {

        menuInflater.inflate(R.menu.menu_stock_toolbar, menu)

        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {

            R.id.menu_stock_toolbar_filter_all -> viewModel.selectAllStockWithFilter(StockViewModel.ALL)
            R.id.menu_stock_toolbar_filter_maior_menor ->  viewModel.selectAllStockWithFilter(StockViewModel.ORDER_BY_DESC)
            R.id.menu_stock_toolbar_filter_menor_maior -> viewModel.selectAllStockWithFilter(StockViewModel.ORDER_BY_ASC)
            R.id.menu_stock_toolbar_filter_finalized -> viewModel.selectAllStockWithFilter(StockViewModel.FINISHED)
            R.id.menu_stock_toolbar_filter_opened -> viewModel.selectAllStockWithFilter(StockViewModel.UNFINISHED)

        }

        return true
        
        //NOTHIN HAPPENS AFTER CHOOSING ONE

    }

} 
使用此viewmodel的活动:

@Dao
interface StockDao {

    @Insert
    suspend fun insert(stock:Stock)

    @Update
    suspend fun update(stock:Stock)

    @Delete
    suspend fun delete(stock:Stock)

    @Query("DELETE FROM stock_table")
    suspend fun deleteAll()

    @Query("SELECT * FROM stock_table")
    fun selectAll():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table WHERE isFinished = 0")
    fun selectAllUnfinished(): Flow<List<Stock>>

    @Query("SELECT * FROM stock_table WHERE isFinished = 1")
    fun selectAllFinished():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table ORDER BY totalSpent DESC")
    fun selectAllOrderByDesc():Flow<List<Stock>>

    @Query("SELECT * FROM stock_table ORDER BY totalSpent ASC")
    fun selectAllOrderByAsc():Flow<List<Stock>>

}
class StockRepository(private val stockDao: StockDao) {

    private lateinit var allStock: Flow<List<Stock>>


    suspend fun insert(stock: Stock) {

        stockDao.insert(stock)

    }

    suspend fun update(stock: Stock) {

        stockDao.update(stock)

    }

    suspend fun delete(stock: Stock) {

        stockDao.delete(stock)

    }

    suspend fun deleteAll() {

        stockDao.deleteAll()

    }

    fun selectAll(): Flow<List<Stock>> {

        allStock = stockDao.selectAll()

        return allStock

    }

    fun selectAllOrderByDesc(): Flow<List<Stock>> {

        allStock = stockDao.selectAllOrderByAsc()

        return allStock

    }

    fun selectAllOrderByAsc(): Flow<List<Stock>> {

        allStock = stockDao.selectAllOrderByAsc()

        return allStock

    }

    fun selectAllFinished(): Flow<List<Stock>> {

        allStock = stockDao.selectAllFinished()

        return allStock

    }

    fun selectAllUnfinished(): Flow<List<Stock>> {

        allStock = stockDao.selectAllUnfinished()

        return allStock

    }


}
class StockViewModel(private val repo: StockRepository) : ViewModel() {

    companion object {

        const val ALL = 0
        const val ORDER_BY_DESC = 1
        const val ORDER_BY_ASC = 2
        const val FINISHED = 3
        const val UNFINISHED = 4

    }

    var allStocks = repo.selectAll().asLiveData()


    fun insert(stock: Stock) = viewModelScope.launch {
        repo.insert(stock)
    }

    fun update(stock: Stock) = viewModelScope.launch {
        repo.update(stock)
    }

    fun delete(stock: Stock) = viewModelScope.launch {
        repo.delete(stock)
    }

    fun deleteAll() = viewModelScope.launch {
        repo.deleteAll()
    }

    fun selectAllStockWithFilter(filter: Int): LiveData<List<Stock>> {

        when (filter) {

            ALL -> allStocks = repo.selectAll().asLiveData()
            ORDER_BY_DESC -> allStocks = repo.selectAllOrderByDesc().asLiveData()
            ORDER_BY_ASC -> allStocks = repo.selectAllOrderByAsc().asLiveData()
            FINISHED -> allStocks = repo.selectAllFinished().asLiveData()
            UNFINISHED -> allStocks = repo.selectAllUnfinished().asLiveData()
        }

        return allStocks

    }


    class StockViewModelFactory(private val repo: StockRepository) : ViewModelProvider.Factory {

        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(StockViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return StockViewModel(repo) as T
            }

            throw IllegalArgumentException("Unknown viewModel class")
        }

    }


}
class FinanceApplication :Application(){

    private val database by lazy {  FinanceDatabase.getInstance(this)}

    val stockRepository by lazy { StockRepository(database.stockDao()) }
}


class StocksActivity : AppCompatActivity() {

    //Layout components
    private lateinit var binder: ActivityStocksBinding
    private lateinit var recyclerView: RecyclerView
    private lateinit var recyclerViewAdapter: StockAdapter

    //ViewModel
    private val viewModel: StockViewModel by viewModels {
        StockViewModel.StockViewModelFactory((application as FinanceApplication).stockRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binder = ActivityStocksBinding.inflate(layoutInflater)
        setContentView(binder.root)
    
        fetchStocks()


    }

    private fun fetchStocks() {


        viewModel.allStocks.observe(this) {

            recyclerViewAdapter.submitList(it)

        }


    }

    private fun initRecyclerViewLayout() {


        val recyclerViewLayoutBinder = binder.includedLayout

        recyclerView = recyclerViewLayoutBinder.stocksRecyclerView
        recyclerViewAdapter = StockAdapter(this)
        recyclerView.adapter = recyclerViewAdapter
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.setHasFixedSize(true)


    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {

        menuInflater.inflate(R.menu.menu_stock_toolbar, menu)

        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {

            R.id.menu_stock_toolbar_filter_all -> viewModel.selectAllStockWithFilter(StockViewModel.ALL)
            R.id.menu_stock_toolbar_filter_maior_menor ->  viewModel.selectAllStockWithFilter(StockViewModel.ORDER_BY_DESC)
            R.id.menu_stock_toolbar_filter_menor_maior -> viewModel.selectAllStockWithFilter(StockViewModel.ORDER_BY_ASC)
            R.id.menu_stock_toolbar_filter_finalized -> viewModel.selectAllStockWithFilter(StockViewModel.FINISHED)
            R.id.menu_stock_toolbar_filter_opened -> viewModel.selectAllStockWithFilter(StockViewModel.UNFINISHED)

        }

        return true
        
        //NOTHIN HAPPENS AFTER CHOOSING ONE

    }

} 

当我进入“活动”时,所有数据都会正常获取,但当我单击某个菜单项对其应用一些过滤器时,什么也没有发生,数据不会更改。如何修复此问题?

所有股票
可能看起来是动态的,因为它是
LiveData
,但请记住,它仍然是对内存中对象的引用。创建
StocksActivity
时,它会在初始状态下观察
allStocks
。为了简单起见,假设
allStocks
指向内存中地址为“A”的对象。最终调用
selectAllStockWithFilter()
时,会更新
allStocks
句柄,以指向位于地址“B”的内存中的
LiveData
的新实例。您面临的问题是
StocksActivity
仍在观察“A”。没有任何消息表明
allStocks
句柄本身已更改

解决此问题的一种方法是将
allStocks
更改为
MutableLiveData
的实例。随后,每当更新此
allStocks
的内容时,您将更新其内部“值”,而不是重新分配
allStocks
。这允许
ViewModel
通过
StocksActivity
正在观察的同一
LiveData
对象实例泵送新的/更新的值

大概是这样的:

class StockViewModel(private val repo: StockRepository) : ViewModel() {

    ...

    val allStocks = MutableLiveData<List<Stock>>().apply { value = repo.selectAll() }


    ...

    fun selectAllStockWithFilter(filter: Int) {
        when (filter) {
            ALL -> allStocks.postValue(repo.selectAll())
            ORDER_BY_DESC -> allStocks.postValue(repo.selectAllOrderByDesc())
            ORDER_BY_ASC -> allStocks.postValue(repo.selectAllOrderByAsc())
            FINISHED -> allStocks.postValue(repo.selectAllFinished())
            UNFINISHED -> allStocks.postValue(repo.selectAllUnfinished())
        }
    }

    ...

}
类StockViewModel(私有val repo:StockRepository):ViewModel(){
...
val allStocks=MutableLiveData().apply{value=repo.selectAll()}
...
乐趣选择AllStockWithFilter(过滤器:Int){
何时(过滤器){
ALL->allStocks.postValue(repo.selectAll())
ORDER_BY_DESC->allStocks.postValue(repo.selectAllOrderByDesc())
订单由\u ASC->allStocks.postValue(repo.selectAllOrderBySC())
FINISHED->allStocks.postValue(repo.selectAllFinished())
UNFINISHED->allStocks.postValue(repo.selectAllUnfinished())
}
}
...
}

StocksActivity.fetchStocks()
中,初始的“所有”结果通过
observe()
”显示,并显示ViewModel返回的LiveData。从选项菜单中选择后,新的过滤结果是如何过滤的?@homerman当我单击菜单项时,方法
StocksActivity.fetchStocks()
会更改
StocksViewmodel
中的'allStock'变量。至少这是我的意图,还是我想错了?