Home > Software design >  I want to update my adapter in realtime using Room Database , LiveData and Viewmodel. But don't
I want to update my adapter in realtime using Room Database , LiveData and Viewmodel. But don't

Time:09-01

I have an recyclerview adapter whose attribute called timeLeft which means it can count down the time from set time with time now in every single recyclerview item. I want it updated in real time but don't know how. Please help me [Example picture][1] [1]: https://i.stack.imgur.com/8le2s.png Data file

@Parcelize
@Entity(tableName = "task_table")
data class Task(
    //id is the PrimaryKey which is auto generated by Android Room Database
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val date: String,
    val content: String,
    var timeLeft: String,
    var isDone : Boolean
):Parcelable

Dao File

@Dao
interface TaskDao {
    // means it will be just ignore if there is a new exactly same task then we're gonna just ignore it
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addTask(task :Task)

    @Delete
    suspend fun deleteTask(task : Task)

    @Update
    suspend fun  updateTask(task : Task)

    @Query("SELECT * FROM task_table order by timeLeft ASC")
    fun readAllData(): LiveData<MutableList<Task>>
}

Repository File

class TaskRepository (private val taskDao : TaskDao){
    val readAllData : LiveData<MutableList<Task>> = taskDao.readAllData()

    suspend fun addTask(task : Task){
        taskDao.addTask(task)
    }

    suspend fun deleteTask(task : Task)
    {
        taskDao.deleteTask(task)
    }

    suspend fun updateTask(task:Task)
    {
        taskDao.updateTask(task)
    }
}

View Model File

class TaskViewModel(application: Application) : AndroidViewModel(application) {
    val readAllData: LiveData<MutableList<Task>>
    private val repository: TaskRepository

    init {
        val taskDao = TaskDatabase.getDatabase(application).taskDao()
        repository = TaskRepository(taskDao)
        readAllData = repository.readAllData
    }

    fun addTask(task: Task) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.addTask(task)
        }
    }

    fun updateTask(task: Task) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.updateTask(task)
        }
    }

    fun deleteTask(task: Task) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.deleteTask(task)
        }
    }

}

Recycler View Adapter File

package com.example.superbtodo.fragments.list


import android.annotation.SuppressLint
import android.graphics.Paint
import android.text.style.StrikethroughSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.example.superbtodo.R
import com.example.superbtodo.data.Task
import com.example.superbtodo.viewmodel.TaskViewModel

class ListAdapter() : RecyclerView.Adapter<ListAdapter.ViewHolder>() {
    private var tasks = mutableListOf<Task>()

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val contentTextView = itemView.findViewById(R.id.contentTxt) as TextView
        val timeTextView = itemView.findViewById(R.id.timeTxt) as TextView
        val timeLeftTextView = itemView.findViewById(R.id.timeLeftTxt) as TextView
        var isDoneCheckBox = itemView.findViewById(R.id.checkBtn) as RadioButton
        val taskLayout = itemView.findViewById(R.id.taskLayout) as RelativeLayout
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val itemView =
            LayoutInflater.from(parent.context).inflate(R.layout.task_layout, parent, false)
        return ViewHolder(itemView)
    }

    @SuppressLint("ResourceAsColor")
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentItem = tasks[position]
        holder.contentTextView.text = currentItem.content
        holder.timeTextView.text = currentItem.date
        holder.timeLeftTextView.text = currentItem.timeLeft
        holder.isDoneCheckBox.isChecked = currentItem.isDone
        holder.taskLayout.setOnClickListener {
            val action =
                ListFragmentDirections.actionListFragmentToUpdateTaskDialogFragment(currentItem)
            holder.itemView.findNavController().navigate(action)
        }
        if (holder.isDoneCheckBox.isChecked) {
            holder.timeLeftTextView.visibility = View.GONE
            holder.contentTextView.apply {
                paintFlags = paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
                setTextColor(R.color.gone)
            }
            holder.timeTextView.apply {
                paintFlags = paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
                setTextColor(R.color.gone)
            }
        } else {
   holder.timeLeftTextView.visibility = View.VISIBLE
            holder.contentTextView.apply {
                paintFlags = 0
                setTextColor(R.color.black)
            }
            holder.timeTextView.apply {
                paintFlags = 0
                setTextColor(R.color.black)
            }
        }

    }

    override fun getItemCount(): Int {
        return tasks.size
    }


    @SuppressLint("NotifyDataSetChanged")
    fun setData(task: MutableList<Task>) {
        this.tasks = task as MutableList<Task>
        notifyDataSetChanged()
    }

    enter code here
    fun getTaskAt(position: Int): Task {
        return tasks[position]
    }
}

CodePudding user response:

Repository File

get live data from database in Repository and return to view model

    fun getLiveDataOfTask():MutableLiveData<MutableList<Task>> {
        return TaskDatabase.getDatabase(application).taskDao().readAllData()
    }

Add In View model class

    fun getAllDataTask() = repository.readAllData

In Activity

 viewModel?.getAllDataTask()?.observe(this) {
        //new Data come hear every time when data was change 
        changeAdapterData()
    }

In Adapter

fun updateList(list: MutableList<Task>) {
    this.list = list
    notifyDataSetChanged()
}

And if you went to update only time in adapter item from save time and current time difference then add below code in adapter and ignore above code

//global variable
 private var handler: android.os.Handler? = null
 var hourly = SimpleDateFormat("ss") // add your time formate

    // in onBindViewHolder
    handler = Handler(Looper.getMainLooper())
    var periodicUpdate: Runnable? = null
    periodicUpdate = Runnable {
        try {
            holder.holderItemView.textView.text = hourly.format(System.currentTimeMillis())
            periodicUpdate?.let { handler?.postDelayed(it, 1000) }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    handler?.post(periodicUpdate)
  • Related