kotlinandroid-recyclerviewandroid-viewbindingactivity-finish

Kotlin -How to call finish() in a RecyclerViewAdapter using Binding (not context)


I need to finish() the Activity that the RecyclerView is in when an item/row is tapped.

I looked this up but most of the answers referred to the old way of doing things when using context and (context as MyActivity).finish(). How can I do the same thing using binding

class MyAdapter(var users: List<User>): RecyclerView.Adapter<MyAdapter.UserViewHolder>() {

    inner class UserViewHolder(private val binding: UserRowBinding): RecyclerView.ViewHolder(binding.root) {

        init {
            binding.root.setOnClickListener {

                val intent = Intent(binding.root.context, NextActivity::class.java)
                binding.root.context.startActivity(intent)

                // call finish() here
            }
        }
    }
}

class MyActivity: App: AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...

        val adapter = MyAdapter(some_array_Of_users)
        binding.recyclerView.adapter = adapter
    }
}

Solution

  • You can also create a listener function on the activity itself.

    In Adapter, you can add a variable for your listener. (or you can just add this as parameter of Adapter)

    val listener: (()->Unit)? = null
    

    In ViewHolder, add listener as your parameter and invoke it in setOnClickListener, it should look like this:

      inner class UserViewHolder(private val binding: UserRowBinding, private val listener: (()->Unit)? = null): RecyclerView.ViewHolder(binding.root) {
    
        init {
            binding.root.setOnClickListener {
                listener?.invoke()
            }
        }
    }
    

    In your Activity, you can just set the variable listener value. In that case, you can set the 'finish()' that you are looking for. Something look like this,

    class MyActivity: App: AppCompatActivity() {
    
    lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    
        val adapter = MyAdapter(some_array_Of_users)
        adapter.listener = { moveToOtherActivity() }
        this.adapter = adapter
    }
    
      private fun moveToOtherActivity() {
          val intent = Intent(this@MainActivity, NextActivity::class.java)
          startActivity(intent)
          finish()
        }
    }
    

    or just add a parameter in your adapter,

    class MyAdapter(var users: List<User>, val listener: (()->Unit?=null): RecyclerView.Adapter<MyAdapter.UserViewHolder>()
    

    And in Activity,

     val adapter = MyAdapter(some_array_Of_users, {moveToOtherActivity()})
    

    I hope this helps.