如何使用 LiveData 进行搜索?
How to use LiveData for searching?
我有一个 ViewModel,它具有 class 课程
数组列表的 MutableLiveData
private var coursesList: MutableLiveData<ArrayList<Course>> = MutableLiveData()
此 coursesList 填充了从 API(通过 Retrofit)获得的数据:coursesList.postValue(response.body())
现在,用户可以通过课程名称搜索课程。我的搜索功能是遍历 coursesList 的元素并检查其名称是否与用户键入的名称相同。它 returns 一个 arrayList,其中包含以键入的名称开头的课程(此列表稍后被发送到一个片段,该片段将其传递给一个适配器以显示在 recyclerview 中):
fun getCoursesList(): MutableLiveData<ArrayList<Course>> {
return coursesList
}
fun searchCourses(searchString: String): ArrayList<Course> {
val resultsList: ArrayList<Course> = ArrayList()
if (getCoursesList().value == null) return resultsList
if (getCoursesList().value!!.size > 0) {
for (course in getCoursesList().value!!.iterator()) {
if (course.name.toLowerCase(Locale.ROOT).startsWith(searchString)) {
resultsList.add(course)
}
}
}
resultsList.sortBy { it.price }
return resultsList
}
这个功能有效,但我的导师要求我使用 LiveData 进行搜索,但没有给出任何额外的提示。
所以我的问题是如何使用 LiveData 进行搜索?我试图寻找答案,我看到一些人使用了 LiveDataTransformations.switchMap,但他们都在使用 RoomDAO,我无法根据我的代码对其进行调整。
非常感谢任何帮助。提前致谢。
我很难猜到想要的结果,但一个可能的解决方案是对搜索的字符串也使用实时数据。然后将它们与 coursesList 实时数据组合成搜索课程的实时数据,例如这样。
val searchStringLiveData: MutableLiveData<String> = MutableLiveData()
val coursesListLiveData: MutableLiveData<ArrayList<Course>> = MutableLiveData()
val searchedCourses: MediatorLiveData<ArrayList<Course>> = MediatorLiveData()
init {
searchedCourses.addSource(searchStringLiveData) {
searchedCourses.value = combineLiveData(searchStringLiveData, coursesListLiveData)
}
searchedCourses.addSource(coursesListLiveData) {
searchedCourses.value = combineLiveData(searchStringLiveData, coursesListLiveData)
}
}
fun combineLiveData(searchStringLiveData: LiveData<String>, coursesListLiveData: LiveData<ArrayList<Course>> ): ArrayList<Course> {
// your logic here to filter courses
return ArrayList()
}
我没有 运行 代码,所以我不能 100% 确定它是否有效,但我的想法是,每当两个实时数据中的任何一个更改值、搜索字符串或课程时,合并执行函数并将结果设置为 searchedCourses 中介实时数据的值。此外,为了简单起见,我省略了过滤逻辑。
也许这对你有一点帮助,
class YourViewModel(
private val courcesRepository: CourcesRepository
) : ViewModel() {
// Private access - mutableLiveData!
private val _coursesList = MutableLiveData<ArrayList<Course>>()
// Public access - immutableLiveData
val coursesList: LiveData<ArrayList<Course>>
get() = _coursesList
init {
// mutableLiveData initialize, automatic is immutable also initialize
_coursesList.postValue(getCourses())
}
// Here you get your data from repository
private fun getCourses(): ArrayList<Course> {
return courcesRepository.getCources()
}
// Search function
fun searchCourses(searchString: String) {
// you hold your data into this methode
val list: ArrayList<Course> = getCources()
if (searchString.isEmpty()) {
// here you reset the data if search string is empty
_coursesList.postValue(list)
} else {
// here you can search the list and post the new one to your LiveData
val filterList = list.filter {
it.name.toLowerCase(Locale.ROOT).startsWith(searchString)
}
filterList.sortedBy { it.price }
_coursesList.postValue(filterList)
}
}
}
第一个提示 是你应该像下面那样使用 LiveData,这也是 google 的喷气背包团队推荐的。原因是你可以封装LivaData。
第二个技巧是您应该使用 kotlin 惯用的方式来过滤列表。您的代码可读且速度更快。
至少 创建一个存储库 class 来分离应用中的关注点是个好主意。
以及一些对您有用的链接:
https://developer.android.com/jetpack/guide
https://developer.android.com/topic/libraries/architecture/livedata
希望对你有所帮助
我有一个 ViewModel,它具有 class 课程
数组列表的 MutableLiveDataprivate var coursesList: MutableLiveData<ArrayList<Course>> = MutableLiveData()
此 coursesList 填充了从 API(通过 Retrofit)获得的数据:coursesList.postValue(response.body())
现在,用户可以通过课程名称搜索课程。我的搜索功能是遍历 coursesList 的元素并检查其名称是否与用户键入的名称相同。它 returns 一个 arrayList,其中包含以键入的名称开头的课程(此列表稍后被发送到一个片段,该片段将其传递给一个适配器以显示在 recyclerview 中):
fun getCoursesList(): MutableLiveData<ArrayList<Course>> {
return coursesList
}
fun searchCourses(searchString: String): ArrayList<Course> {
val resultsList: ArrayList<Course> = ArrayList()
if (getCoursesList().value == null) return resultsList
if (getCoursesList().value!!.size > 0) {
for (course in getCoursesList().value!!.iterator()) {
if (course.name.toLowerCase(Locale.ROOT).startsWith(searchString)) {
resultsList.add(course)
}
}
}
resultsList.sortBy { it.price }
return resultsList
}
这个功能有效,但我的导师要求我使用 LiveData 进行搜索,但没有给出任何额外的提示。
所以我的问题是如何使用 LiveData 进行搜索?我试图寻找答案,我看到一些人使用了 LiveDataTransformations.switchMap,但他们都在使用 RoomDAO,我无法根据我的代码对其进行调整。
非常感谢任何帮助。提前致谢。
我很难猜到想要的结果,但一个可能的解决方案是对搜索的字符串也使用实时数据。然后将它们与 coursesList 实时数据组合成搜索课程的实时数据,例如这样。
val searchStringLiveData: MutableLiveData<String> = MutableLiveData()
val coursesListLiveData: MutableLiveData<ArrayList<Course>> = MutableLiveData()
val searchedCourses: MediatorLiveData<ArrayList<Course>> = MediatorLiveData()
init {
searchedCourses.addSource(searchStringLiveData) {
searchedCourses.value = combineLiveData(searchStringLiveData, coursesListLiveData)
}
searchedCourses.addSource(coursesListLiveData) {
searchedCourses.value = combineLiveData(searchStringLiveData, coursesListLiveData)
}
}
fun combineLiveData(searchStringLiveData: LiveData<String>, coursesListLiveData: LiveData<ArrayList<Course>> ): ArrayList<Course> {
// your logic here to filter courses
return ArrayList()
}
我没有 运行 代码,所以我不能 100% 确定它是否有效,但我的想法是,每当两个实时数据中的任何一个更改值、搜索字符串或课程时,合并执行函数并将结果设置为 searchedCourses 中介实时数据的值。此外,为了简单起见,我省略了过滤逻辑。
也许这对你有一点帮助,
class YourViewModel(
private val courcesRepository: CourcesRepository
) : ViewModel() {
// Private access - mutableLiveData!
private val _coursesList = MutableLiveData<ArrayList<Course>>()
// Public access - immutableLiveData
val coursesList: LiveData<ArrayList<Course>>
get() = _coursesList
init {
// mutableLiveData initialize, automatic is immutable also initialize
_coursesList.postValue(getCourses())
}
// Here you get your data from repository
private fun getCourses(): ArrayList<Course> {
return courcesRepository.getCources()
}
// Search function
fun searchCourses(searchString: String) {
// you hold your data into this methode
val list: ArrayList<Course> = getCources()
if (searchString.isEmpty()) {
// here you reset the data if search string is empty
_coursesList.postValue(list)
} else {
// here you can search the list and post the new one to your LiveData
val filterList = list.filter {
it.name.toLowerCase(Locale.ROOT).startsWith(searchString)
}
filterList.sortedBy { it.price }
_coursesList.postValue(filterList)
}
}
}
第一个提示 是你应该像下面那样使用 LiveData,这也是 google 的喷气背包团队推荐的。原因是你可以封装LivaData。
第二个技巧是您应该使用 kotlin 惯用的方式来过滤列表。您的代码可读且速度更快。
至少 创建一个存储库 class 来分离应用中的关注点是个好主意。
以及一些对您有用的链接:
https://developer.android.com/jetpack/guide
https://developer.android.com/topic/libraries/architecture/livedata
希望对你有所帮助