I am trying to update recycler view after clearing room database. On click of clear button in pop up menu data from room database is cleared up recycler view is not updated.
Error can be seen Error recording
Repository Code is
package com.example.todoapp.database
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.example.todoapp.data.TaskDate
class Repository(private val taskDatabase: TaskDatabase) {
suspend fun addTask(taskEntity: TaskEntity)=taskDatabase.dao().addTask(taskEntity)
suspend fun deleteTask(taskEntity: TaskEntity)=taskDatabase.dao().deleteTask(taskEntity)
suspend fun updateTask(taskEntity: TaskEntity)=taskDatabase.dao().updatetask(taskEntity)
suspend fun clearTable()=taskDatabase.dao().clearTable()
fun getAllDatabyDate(date:String)=taskDatabase.dao().getAllDatabyDate(date)
private fun getAllDateTaskUnCompleted()=taskDatabase.dao().getAllDateTaskUnCompleted()
private fun getAllDateTaskCompleted()=taskDatabase.dao().getAllDateTaskCompleted()
fun task_date_Uncompleted():LiveData<List<TaskDate>> {
val taskDatesLiveData = MediatorLiveData<List<TaskDate>>()
taskDatesLiveData.addSource(getAllDateTaskUnCompleted()) { uniqueDates ->
val taskDates = mutableListOf<TaskDate>()
uniqueDates?.forEach { date ->
val tasksForDateLive = getAllDatabyDate(date)
tasksForDateLive.observeForever { tasksForDate ->
taskDates.add(TaskDate(date, tasksForDate))
taskDatesLiveData.value = taskDates
}
}
}
return taskDatesLiveData
}
fun task_date_Completed():LiveData<List<TaskDate>> {
val taskDatesLiveData = MediatorLiveData<List<TaskDate>>()
taskDatesLiveData.addSource(getAllDateTaskCompleted()) { uniqueDates ->
val taskDates = mutableListOf<TaskDate>()
uniqueDates?.forEach { date ->
val tasksForDateLive = getAllDatabyDate(date)
tasksForDateLive.observeForever { tasksForDate ->
taskDates.add(TaskDate(date, tasksForDate))
taskDatesLiveData.value = taskDates
}
}
}
return taskDatesLiveData
}
}
View model code is
package com.example.todoapp.database
import android.app.Application
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.example.todoapp.data.TaskDate
import kotlinx.coroutines.launch
class TaskViewModel(application: Application,private val repository: Repository):AndroidViewModel(application) {
fun addTask(taskEntity: TaskEntity)=viewModelScope.launch {
repository.addTask(taskEntity)
}
fun deleteTask(taskEntity: TaskEntity)=viewModelScope.launch {
repository.deleteTask(taskEntity)
}
fun updateTask(taskEntity: TaskEntity)=viewModelScope.launch {
repository.updateTask(taskEntity)
}
fun clearTable()=viewModelScope.launch {
repository.clearTable()
}
private val _response=MutableLiveData<List<TaskDate>>()
val getTaskDatesUncompleted:LiveData<List<TaskDate>>
get()=_response
init{
updateResponseUncompletedTask()
}
fun updateResponseUncompletedTask() =viewModelScope.launch {
repository.task_date_Uncompleted().observeForever{listUncompletedTask->
_response.postValue(listUncompletedTask)
}
}
}
Show fragment code is
package com.example.todoapp.Fragment
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.ContextMenu
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.example.todoapp.Adapter.TaskDateAdapter
import com.example.todoapp.Helper.SwipeViewHelper
import com.example.todoapp.MainActivity
import com.example.todoapp.R
import com.example.todoapp.data.TaskDate
import com.example.todoapp.database.TaskEntity
import com.example.todoapp.database.TaskViewModel
import com.example.todoapp.databinding.FragmentShowTaskBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.lang.Exception
class ShowTaskFragment : Fragment(R.layout.fragment_show_task){
private lateinit var binding: FragmentShowTaskBinding
private lateinit var dateAdapter: TaskDateAdapter
private lateinit var viewModel: TaskViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding=DataBindingUtil.inflate(inflater,R.layout.fragment_show_task,container,false)
//view model initialise
viewModel=(activity as MainActivity).viewModel
//set Up Recycler View
setUpRecyclerView()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//setUp Add button
loadAddFrag()
//set up popup menu
setUpMenu()
}
private fun loadAddFrag(){
binding.btnadd.setOnClickListener{
findNavController().navigate(R.id.action_showTaskFragment_to_addTaskFragment)
}
}
private fun setUpRecyclerView(){
dateAdapter= TaskDateAdapter(viewModel)
binding.taskDateRv.apply {
setHasFixedSize(true)
layoutManager=LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false)
adapter=dateAdapter
}
activity?.let {
viewModel.getTaskDatesUncompleted.observe(viewLifecycleOwner){task_dateList ->
dateAdapter.differDate.submitList(task_dateList)
}
}
}
private fun setUpMenu(){
val popupMenu=PopupMenu(requireContext(),binding.imageMenu)
popupMenu.inflate(R.menu.main_menu)
popupMenu.setOnMenuItemClickListener {
when(it.itemId){
// On click of Clear Button
R.id.clearAll_menu -> {
viewModel.clearTable()
viewModel.updateResponseUncompletedTask()
dateAdapter.notifyDataSetChanged()
Toast.makeText(context,"Clear",Toast.LENGTH_SHORT).show()
true}
else ->{
findNavController().navigate(R.id.action_showTaskFragment_to_completedTaskFragment)
true
}
}
}
binding.imageMenu.setOnClickListener{
popupMenu.show()
}
}
}
code for Task adapter is
package com.example.todoapp.Adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.todoapp.Helper.SwipeViewHelper
import com.example.todoapp.MainActivity
import com.example.todoapp.data.TaskDate
import com.example.todoapp.database.TaskEntity
import com.example.todoapp.database.TaskViewModel
import com.example.todoapp.databinding.TaskDateModelBinding
class TaskDateAdapter(val viewModel: TaskViewModel,var type:Int=0):RecyclerView.Adapter<TaskDateAdapter.ViewHolder>() {
/*
* 0 - > Uncompleted Task
* 1 - > completed Task
*
* */
class ViewHolder(var taskDateModelBinding: TaskDateModelBinding):RecyclerView.ViewHolder(taskDateModelBinding.root)
private lateinit var taskAdapter: TaskAdapter
private lateinit var taskCompletedAdapter: TaskCompletedAdapter
// creating diff
private val differCallBack= object :DiffUtil.ItemCallback<TaskDate>(){
override fun areItemsTheSame(oldItem: TaskDate, newItem: TaskDate): Boolean {
return oldItem.date==newItem.date &&
oldItem.taskDateList==newItem.taskDateList
}
override fun areContentsTheSame(oldItem: TaskDate, newItem: TaskDate): Boolean {
return oldItem==newItem
}
}
val differDate=AsyncListDiffer(this,differCallBack)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(TaskDateModelBinding.inflate(LayoutInflater.from(parent.context),parent,false))
}
override fun getItemCount(): Int {
return differDate.currentList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val curr= differDate.currentList[position]
holder.taskDateModelBinding.taskDateTdm.text=curr.date
taskCompletedAdapter= TaskCompletedAdapter(viewModel)
taskAdapter= TaskAdapter(viewModel)
if(type==1){
holder.taskDateModelBinding.taskRv.adapter=taskCompletedAdapter
taskCompletedAdapter.differ.submitList(curr.taskDateList)
}
else{
holder.taskDateModelBinding.taskRv.adapter=taskAdapter
taskAdapter.differ.submitList(curr.taskDateList)
}
//val swipe
setUpSwipe(holder.taskDateModelBinding.taskRv)
}
private fun setUpSwipe(recyclerView: RecyclerView){
var swipeHelper=object: SwipeViewHelper(){
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
when(direction){
ItemTouchHelper.LEFT ->{
if(type==1){
taskCompletedAdapter.deleteTask(viewHolder.adapterPosition)
}else {
taskAdapter.deleteTask(viewHolder.adapterPosition)
}
}
}
super.onSwiped(viewHolder, direction)
}
}
val touchHelper=ItemTouchHelper(swipeHelper)
touchHelper.attachToRecyclerView(recyclerView)
}
}
Room Dao Code is
package com.example.todoapp.database
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.todoapp.data.TaskDate
@Dao
interface TaskDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addTask(taskEntity: TaskEntity)
@Query("Select * from TaskEntity where Date==:date order by id")
fun getAllDatabyDate(date:String):LiveData<List<TaskEntity>>
@Query("Select Distinct Date from TaskEntity where TaskStatus=0 order by Date,id ")
fun getAllDateTaskUnCompleted():LiveData<List<String>>
@Query("Select Distinct Date from TaskEntity where TaskStatus=1 order by Date,id ")
fun getAllDateTaskCompleted():LiveData<List<String>>
@Query("Delete From TaskEntity")
suspend fun clearTable()
@Update
suspend fun updatetask(taskEntity: TaskEntity)
@Delete
suspend fun deleteTask(taskEntity: TaskEntity)
}
I tried a lot but can't find solution for this. Kindly help me is resolving this issue.
I have gone through your code and solved the issue. Update your task_date_Uncompleted
function as below :
fun task_date_Uncompleted():LiveData<List<TaskDate>> {
val taskDatesLiveData = MediatorLiveData<List<TaskDate>>()
taskDatesLiveData.addSource(getAllDateTaskUnCompleted()) { uniqueDates ->
taskDatesLiveData.postValue(emptyList())
val taskDates = mutableListOf<TaskDate>()
uniqueDates?.forEach { date ->
val tasksForDateLive = getAllDatabyDate(date)
tasksForDateLive.observeForever { tasksForDate ->
taskDates.add(TaskDate(date, tasksForDate))
taskDatesLiveData.value = taskDates
}
}
}
return taskDatesLiveData
}
Basically need to add taskDatesLiveData.postValue(emptyList())
at line 24
in repository
class.