我有一个习惯应用程序,用户可以添加不同类型的新习惯,并将习惯标记为已完成/未完成.
使用芯片的习惯片段显示了两种不同的习惯类型"积极的"和"消极的",所以当用户判断积极的芯片时,回收器查看得到积极的习惯和使用负面芯片的相同的东西.
Here's How this operation work.个
This is my DAO Code个
@Query("SELECT * FROM HABIT_TABLE WHERE type = :type ORDER BY isCompleted ASC")
fun getAllHabitsByType(type: String): Flow<List<HabitEntity>>
@Query("UPDATE HABIT_TABLE SET isCompleted = :isCompleted WHERE habitId = :habitId")
suspend fun updateHabitByCompleted(habitId: Long, isCompleted: Boolean)
And In my Repository, I map from "HabitEntity" to "HabitModel". So the function should return Flow<List< Habit>>.个
override fun getAllHabitsByType(type: HabitType): Flow<List<Habit>> {
return channelFlow {
dao.getAllHabitsByType(type.pathName).collect { habits ->
send(habitMapper.map(habits))
}
}
}
override suspend fun updateHabitByCompleted(habit: Habit, isCompleted: Boolean) {
dao.updateHabitByCompleted(habit.id, isCompleted)
}
一百零二
override fun getAllHabitsByType(type: HabitType): Flow<List<Habit>> {
return flow {
dao.getAllHabitsByType(type.pathName).map {
emit(habitMapper.map(it))
}
}
}
Ok, after that I collect the latest changes in ViewModel and observe them in RecyclerView. Here's my ViewModel function.个
private val _habitsList = MutableLiveData<List<Habit>>()
val habitsList: LiveData<List<Habit>> get() = _habitsList
private var currentHabitType = HabitType.POSITIVE
private fun getHabitsByType(habitType: HabitType) {
viewModelScope.launch {
repository.getAllHabitsByType(habitType).collectLatest {
_habitsList.postValue(it)
}
}
}
override fun updateHabitByCompleted(habit: Habit, isCompleted: Boolean) {
viewModelScope.launch {
repository.updateHabitByCompleted(habit, isCompleted)
getHabitsByType(currentHabitType)
}
}
fun onChipTypeClick(habitType: HabitType) {
currentHabitType = habitType
getHabitsByType(habitType)
}
And Here's my HabitsFragment.个
lateinit var habitsAdapter: HabitsAdapter
private fun initRecyclerVIew() {
habitsAdapter = HabitsAdapter(emptyList(), viewModel)
binding.habitsRecyclerView.adapter = habitsAdapter
}
private fun observeEvents() {
viewModel.apply {
....
habitsList.observe(viewLifecycleOwner) {
habitsAdapter.setItems(it)
}
}
}
Chips XML code In Habits Fragment个
<data>
<variable
name="viewModel"
type="com.moataz.mohareb.presentation.habits.viewmodel.HabitsViewModel" />
<variable
name="habitType"
type="com.moataz.mohareb.core.enums.HabitType" />
</data>
<com.google.android.material.chip.ChipGroup
style="@style/Widget.Material3.Chip.Suggestion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:selectionRequired="true"
app:singleSelection="true">
<com.google.android.material.chip.Chip
style="@style/ChipStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:onClick="@{() -> viewModel.onChipTypeClick(habitTYpe.POSITIVE)}"
android:text="@string/good_habit"
app:chipStrokeColor="@android:color/transparent" />
<com.google.android.material.chip.Chip
style="@style/ChipStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{() -> viewModel.onChipTypeClick(habitTYpe.NEGATIVE)}"
android:text="@string/bad_habit"
app:chipStrokeColor="@android:color/transparent" />
</com.google.android.material.chip.ChipGroup>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/habits_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="6dp"
android:orientation="vertical"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/horizontal_chips_scroll_view"
tools:listitem="@layout/item_habit" />
And here's the code of the view changes when clicking on CheckBox completed in the habit using databiding.个
@BindingAdapter(value = ["app:changeTextStatue"])
fun changeTextStatue(textView: TextView, isCompleted: Boolean) {
if (isCompleted) {
textView.paintFlags = textView.paintFlags or android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
} else {
textView.paintFlags =
textView.paintFlags and android.graphics.Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
}
@BindingAdapter(value = ["app:changeCheckBoxStatue"])
fun changeCheckBoxStatue(checkBox: CheckBox, isCompleted: Boolean) {
checkBox.isChecked = isCompleted == true
}
我的问题是
当我 Select 第一个芯片来显示数据并将其标记为完成或未完成时,它工作正常,数据更新没有任何问题.请看这个视频,充分了解https://youtube.com/shorts/bdRd70Me5nk?feature=share
如果我想从第一个芯片转移到另一个芯片,在不完成任何习惯的情况下获得不同的习惯类型,它也非常有效.https://youtube.com/shorts/t0Ma0BAE_Tw?feature=share个
What If I want to mark a habit as completed and want to move from chip good habits to chip bad habits? And also if I have completed habits and want to move to another chip. Here's the problem in these two Situations. The RecycleView performs a very strange beehive process.https://www.youtube.com/shorts/6juhhWxq6_Y
I have tried to search for this problem for 4 days, but I didn't find any solutions that are useful or any that give me a full understanding of my problem.个
注:
- 我try 在Dao中使用"@UPDATE"查询来更新实体,同样也出现了同样的问题.
- 我也try 过将getAllHabitsByType函数从(Dao中的Flow to Suspend)改为,当将一个习惯从NotComplete更改为Complete并移动到另一个芯片时,它运行得很好,但当然,当更新习惯状态以更新回收视图时,我需要在ViewModel中再次调用getAllHabits Fun,以及从另一个片段添加新习惯时的问题,我需要流在添加新习惯的时刻更新到我的回收视图**
以下是我在GitHub上的项目源代码,以全面理解我的代码https://github.com/MoatazBadawy/Mohareb
Thank you.