【发布时间】:2021-09-24 16:48:38
【问题描述】:
我有一个数据集,其中包含用户的 GradeEntity 对象,其中包含对其关联的 SubjectEntity 实例的引用。我现在需要允许用户根据两个选项过滤该数据集:
- 主题标题
- 日期范围
这就是我在过滤过程中要遵循的逻辑。 假设初始数据集包含两个年级实体:
- 年级(标题:数学,日期:7 月 11 日)
- 年级(标题:数学,日期:7 月 14 日)
现在让我们假设用户根据“数学”对成绩进行排序,但尚未选择日期范围。显示了所有相应的成绩,但现在用户想要在过滤的数据集上应用日期范围。他/她选择从 7 月 1 日到 7 月 12 日的范围。所以,现在用户只能看到一年级实体。现在假设他们想要将日期范围过滤器从 7 月 1 日更改为 7 月 15 日。我希望他们现在能够看到两个成绩。这意味着我不能像在当前 ViewModel 代码中那样重新过滤过滤后的数据集。当用户首先根据日期过滤,然后是主题,然后选择另一个主题时,同样的问题。这种过滤过程的最佳方法是什么?
现在我正在使用共享的MutableLiveData<List<GradeEntity>> 变量,但这不适用于我上面提到的所有情况。
ViewModel.kt:
class GradesViewModel(private val database: AppDatabase) : ViewModel() {
private val _grades: MutableLiveData<List<GradeEntity>> = MutableLiveData(emptyList())
val grades: LiveData<List<GradeEntity>> = _grades
private val _filteredGrades: MutableLiveData<List<GradeEntity>> = MutableLiveData(emptyList())
val filteredGrades: LiveData<List<GradeEntity>> = _filteredGrades
init {
getGradesFromDB()
}
private fun getGradesFromDB() {
viewModelScope.launch(Dispatchers.IO) {
val grades = database.getGradeDao().getAllGrades()
if (grades.isNotEmpty() && grades != _grades.value) _grades.postValue(grades)
}
}
fun getSubjectTitlesRelatedToGrades(): MutableSet<String> {
val subjectTitles: MutableSet<String> = mutableSetOf("All Subjects")
for (gradeEntity in grades.value!!) {
subjectTitles.add(gradeEntity.subject.title)
}
return subjectTitles
}
fun filterGradesBasedOnSubject(subjectTitle: String) {
viewModelScope.launch {
filterGradesBasedOnSubjectAsync(subjectTitle)
}
}
fun filterGradesBasedOnDate(startDate: Date, endDate: Date) {
viewModelScope.launch {
filterGradesBasedOnDateAsync(startDate, endDate)
}
}
private suspend fun filterGradesBasedOnSubjectAsync(subjectTitle: String) {
val filteredData = viewModelScope.async(Dispatchers.IO) {
if (filteredGrades.value!!.isEmpty()) {
grades.value?.stream()
?.filter { gradeEntity -> gradeEntity.subject.title == subjectTitle }?.toList()
?: emptyList()
} else filteredGrades.value?.stream()
?.filter { gradeEntity -> gradeEntity.subject.title == subjectTitle }?.toList()
?: emptyList()
}
_filteredGrades.postValue(filteredData.await())
}
private suspend fun filterGradesBasedOnDateAsync(startDate: Date, endDate: Date) {
val filteredData = viewModelScope.async(Dispatchers.IO) {
val formatter = SimpleDateFormat("MMMM dd yyyy", Locale.getDefault())
return@async if (filteredGrades.value!!.isEmpty()) {
grades.value?.stream()
?.filter { gradeEntity ->
formatter.parse(gradeEntity.formattedDateTime).after(startDate) &&
formatter.parse(gradeEntity.formattedDateTime).before(endDate)
}?.toList()
?: emptyList()
} else {
filteredGrades.value?.stream()
?.filter { gradeEntity ->
formatter.parse(gradeEntity.formattedDateTime).after(startDate) &&
formatter.parse(gradeEntity.formattedDateTime).before(endDate)
}?.toList()
?: emptyList()
}
}
_filteredGrades.postValue(filteredData.await())
}
}
【问题讨论】:
标签: android kotlin mvvm kotlin-coroutines