skip to Main Content

I want btnTodoDone to show how many tasks are done. So in the adapter I add done items to dones. After that I need to get dones’ size in main activity and set it to the button’s text. But there is always 0 because main activity doesn’t see the changes of this list. It sees only empty mutable list. What to do?

TodoAdapter

package com.bignerdranch.android.taskmaster



import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView



import androidx.recyclerview.widget.RecyclerView
import com.bignerdranch.android.taskmaster.databinding.ItemTodoBinding



class TodoAdapter(
    private var todos: MutableList<Todo>, private var dones: MutableList<Todo>
):RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {

    class TodoViewHolder( ItemTodoBinding: ItemTodoBinding): RecyclerView.ViewHolder(ItemTodoBinding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {

        val layoutInflater = LayoutInflater.from(parent.context)
        val ItemTodoBinding = ItemTodoBinding.inflate(layoutInflater, parent, false)

        return TodoViewHolder(
            return TodoViewHolder(ItemTodoBinding)
        )


    }



    private fun toggleStrikeThrough(tvTodoTitle: TextView, isChecked:Boolean){
        if(isChecked){
            tvTodoTitle.paintFlags = tvTodoTitle.paintFlags or STRIKE_THRU_TEXT_FLAG
        }else{
            tvTodoTitle.paintFlags = tvTodoTitle.paintFlags and STRIKE_THRU_TEXT_FLAG.inv()
        }
    }

    override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
          val curTodo = todos[position]

          holder.itemView.apply{

              val tvTodoTitle = findViewById(R.id.tvTodoTitle) as TextView
              val tvTodoDate = findViewById(R.id.tvTodoDate) as TextView
              tvTodoTitle.text = curTodo.title
              tvTodoDate.text=curTodo.date

              val cbDone = findViewById(R.id.cbDone) as CheckBox
              cbDone.isChecked = curTodo.isChecked
              toggleStrikeThrough(tvTodoTitle, curTodo.isChecked)
              cbDone.setOnCheckedChangeListener { _, isChecked ->
                  toggleStrikeThrough(tvTodoTitle, isChecked)
                  curTodo.isChecked = !curTodo.isChecked


              }


              cbDone.setOnClickListener(View.OnClickListener{
                  todos.removeAll{todo->
                          todo.isChecked

                      }
                  dones.add(curTodo)

                      notifyDataSetChanged()

              })



        }
    }

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



}

MainActivity

package com.bignerdranch.android.taskmaster



import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle



import androidx.recyclerview.widget.LinearLayoutManager
import com.bignerdranch.android.taskmaster.databinding.ActivityMainBinding



class MainActivity : AppCompatActivity() {

    private lateinit var todoAdapter:TodoAdapter
    private lateinit var binding: ActivityMainBinding
    private var todos: MutableList<Todo> = mutableListOf()
    private var dones: MutableList<Todo> = mutableListOf()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(binding.root)




        todoAdapter = TodoAdapter(todos, dones)
        binding.rvTodoItems.adapter = todoAdapter
        binding.rvTodoItems.layoutManager = LinearLayoutManager(this)


        binding.btnAddTodo.setOnClickListener{
            NewTaskSheet().show(supportFragmentManager,"NewTaskTag")
            }
        supportFragmentManager.setFragmentResultListener("requestKey",this){ requestKey,bundle ->
            val newTodo=bundle.getSerializable("bundleKey") as Todo
            todos.add(newTodo)
            todoAdapter.notifyDataSetChanged()
        }

        binding.btnTodoDone.setOnClickListener{

            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }
        binding.btnTodoDone.text="Done"+"(${dones.size.toString()})"
    }



}

2

Answers


  1. make a public method in adapter

    public fun getDoneList(): MutableList{
    return dones }

    and get updated List in Activity by calling this method

    val updatedDoneList = todoAdapter.getDoneList()

    Login or Signup to reply.
  2. This is because you set the button’s text but there is nothing to update the text at every dataSetChange. You will need a persistent value that is notified of it’s changes that has a callback that updates your button text value. You should keep your data as live data in a view model to also make sure your data is not lost durring the activit’s lifecycle.
    So you would have something like :

    class MainActivityViewModel():ViewModel(){
            
            private val _dones = MutableLiveData<MutableList<Todo>()
            val dones: LiveData<MutableList<Todo>>
            get() = _saveButtonText
    
            fun updateDones(newVal:Todo){ _dones.value.add(newVal)}
    
    }
    

    And to make the updates visible , you should pass the VM to your adapter as a param or make your adapter an inner class of MainActivity.

    class TodoAdapter(
    private var todos: MutableList<Todo>, private var viewModel : ActivityViewModel):RecyclerView.Adapter<TodoAdapter.TodoViewHolder>()
    

    Replace the code in your adapter acordingly : dones.add(curTodo) should be now viewModel.updateDones(curTodo)

    And in your MainActivity you must declare and create the view model and set an observer to that livedata:

    class MainAtivity(){
    ...
     private val viewModel : MainActivityViewModel by viewModels()
    ...
     onCreate(){ 
          ...
          todoAdapter = TodoAdapter(todos, viewModel)
          ...
          viewModel.dones.observe(this@MainActivity){
                  binding.btnTodoDone.text="Done"+"(${it.size.toString()})"
              }
     }
     ...
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search