RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1000317
Accepted
V.March
V.March
Asked:2020-07-08 03:00:36 +0000 UTC2020-07-08 03:00:36 +0000 UTC 2020-07-08 03:00:36 +0000 UTC

如何使用 ViewModel 的 LiveData 订阅从同一个 Room 数据库表中获取不同的列表?

  • 772

有一个基地Room。LiveData我通过and得到了整个列表ViewModel。

道:

@Query("SELECT * FROM tasks")
fun getAllTask(): LiveData<List<Tasks>>

存储库:

fun getAllTasks(tasksDao: TasksDao): LiveData<List<Tasks>> {
    this.tasksDao = tasksDao
    return tasksDao.getAllTask()
}

视图模型:

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

    private val repository: OwnRepository

    val allTasks:LiveData<List<Tasks>>


    init {

            val tasksDao = AppDatabase.getDatabase(application, viewModelScope).tasksDao()

            repository = OwnRepository()

            allTasks = repository.getAllTasks(tasksDao)

        }
}

分段:

class TasksFragment : Fragment() {

private lateinit var ownViewModel: OwnViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    ownViewModel = ViewModelProviders.of(this).get(OwnViewModel::class.java)
}


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {

        val view = inflater.inflate(R.layout.fragment_tasks_list, container, false)
        val recyclerView = view.findViewById<RecyclerView>(R.id.listTasks)

        // Set the adapter
        val adapter = MyTasksRecyclerViewAdapter(listener, context!!)

        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(context)


        ownViewModel.allTasks.observe(viewLifecycleOwner, Observer { tasksList ->
            tasksList?.let {

                adapter.setTaskList(it)
            }
        })

        return view
    }
}

我将结果列表传递给适配器并填写RecyclerView

需要从同一个表中获取一个不完整的列表,但通过某些参数过滤。

事实上,现在随着数据库的变化,适配器将收到一个带有变化的新列表。但是获取过滤列表的正确方法是什么?

我想出了几个选择。

第一个选项- 逻辑上应该这样做 - 是从基础获取与参数对应的新元素列表,someId例如,通过这样的请求:

@Query("SELECT * FROM tasks WHERE some_id = :someId")
fun getTaskBySomeId(someId: Long): LiveData<List<Tasks>>

然后传递给Repository,然后传递给 ,然后传递ViewModel给adapter。但是当您尝试进行此传输并替换适配器中的列表时,会出现很多不一致的情况。例如,我正在尝试分支。如果filterIsTrue == true那时我请求截断列表:

重新设计的 ViewModel:

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

    private val repository: OwnRepository

    val allTasks: LiveData<List<Tasks>>


    init {

        val tasksDao = AppDatabase.getDatabase(application, viewModelScope).tasksDao()

        repository = OwnRepository()

        allTasks = getTasksList(tasksDao)

    }

    private fun getTasksList(tasksDao: TasksDao): LiveData<List<Tasks>> {

        if (filterIsTrue) {

            return repository.getFilteredTasks(tasksDao, someId)
        } else {
            return repository.getAllTasks(tasksDao)
        }

    }
}

LiveData但显然没有订阅新的,所以列表没有更新。有一个想法是杀死旧的并获得一个新的LiveData并进行另一个订阅。我不确定这是否可行,这是一个非常令人困惑的代码。

第二种选择是制作两个LiveData,然后在适当的时候切换。但是后来我将有 2 个订阅,每次我都会收到 2 个列表ViewModel:完整和部分 - 不合理,但更容易。您可以取消不必要的订阅并订阅新的订阅LiveData,但这更加困难并且仍然ViewModel会收到 2 个列表。

第三个选项是通过适配器中已有的参数或在将其传递给适配器之前从完整列表中进行选择。不难,但是使用数据库的本质就丢失了。事实证明,我每次都会收到一个完整的列表,然后对其进行迭代,而不是从数据库中获取一个小列表并使用它。

最好的组织方式是什么?

android
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    WiMank
    2020-07-08T03:47:17Z2020-07-08T03:47:17Z

    为了不创建新的 LiveData 并且不返回拐杖,我们为其创建了一个 getter,因此我们总是获得与 Fragment 中的 Observer 订阅相同的 LiveData 实例:

    ownViewModel.getLiveData().observe(viewLifecycleOwner, Observer { tasksList ->
        tasksList?.let { ... }
    

    与其使用变量,不如创建两个方法来获取排序或常规列表,这样会更简单明了,然后我们只需通过 value 分配我们的 LiveData 列表,然后 Observer 接收新数据并更新 UI。

    class OwnViewModel(application: Application) : AndroidViewModel(application) {
    
        private val repository = OwnRepository()
    
        private val allTasks = MutableLiveData<List<Tasks>>
    
        private val tasksDao = AppDatabase.getDatabase(application, viewModelScope).tasksDao()
    
        init {
            allTasks = repository.getAllTasks(tasksDao)
        }
    
        private fun getTasksList(tasksDao: TasksDao) {
            allTasks.value = repository.getAllTasks(tasksDao)
        }
    
        private fun getSortedTasksList(tasksDao: TasksDao) {
            allTasks.value = repository.getFilteredTasks(tasksDao, someId)
        }
    
        fun getLiveData(): LiveData<List<Tasks>> = allTasks
    }
    

    如果您不打算跟踪其中的更改,则无需从 Room 返回 LiveData:

    @Query("SELECT * FROM tasks")
    fun getAllTask():List<Tasks>
    

    我可以建议你阅读谷歌关于应用程序架构的文章(有源链接)

    如果需要跟踪数据库,可以使用以下方法:

    private val triggerLiveData: MutableLiveData<MyType> = MutableLiveData()
    private val liveData: LiveData<MyType> =
        Transformations.switchMap(triggerLiveData) {
            myRepository.getRepoData(it)
        }
    
    fun getData(value: MyType): LiveData<MyType> {
        triggerLiveData.value = value
        return liveData
    }
    

    每次触发器更改时,都会在某个存储库中调用一些方法 + 我们的观察者将订阅一个 liveData 实例,该实例将从存储库接收数据。

    • 5

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5