CEO tech4lifeapps
CEO tech4lifeapps

Reputation: 895

Kotlin: How do I call a DialogFragment from within an Adapter class?

I have a MainAdapter.kt class that handles a RecyclerView. In its Holder class, I use a OnLongClickListener that calls a function deleteCategory(categoryId) to delete an entry in my Firebase database. This works perfectly:

class CategoryHolder(val customView: View, var category: Category? = null) : RecyclerView.ViewHolder(customView) {
    private val TAG = CategoryHolder::class.java.simpleName

    fun bind(category: Category) {
        with(category) {
            customView.textView_name?.text = category.name
            customView.textView_description?.text = category.description

            val categoryId = category.id

            customView.setOnClickListener {
                    // do something
            }

            customView.setOnLongClickListener(
                    {
                       deleteCategory(categoryId)
                       true
                    }
            )
        }
    }

    private fun deleteCategory(categoryId: String) {
        val database = FirebaseDatabase.getInstance()

        val myRef = database.getReference("categories").child(categoryId)
        myRef.removeValue()
        Log.d(TAG, "Category with id " + categoryId + " deleted")
    }
}

But I rather want to call a function inside a DialogFragment class instead of the deleteCategory(id) function, like this:

  // Create an instance of a DeleteCategoryDialogFragment and show it
  fun showDeleteCategoryDialog(view: View, categoryId: String) {
      val dialog = DeleteCategoryDialogFragment.newInstance(categoryId)
      dialog.show([email protected], 
      "DeleteCategoryDialog")
  }

This gives me a "Unresolved reference: @MainActivity" error. How can I solve this? Is there a way to get hold of categoryId (of type String) in my MainActivity? This would allow me to move the function showDeleteCategoryDialog to MainActivity and solve the problem.

Upvotes: 0

Views: 3720

Answers (3)

CEO tech4lifeapps
CEO tech4lifeapps

Reputation: 895

Here is, in detail, how this was solved:

  1. In class CategoryHolder

    customView.setOnLongClickListener(
        {
          showDeleteCategoryDialog(it, categoryId)
          true
        } 
    )
    
  2. In function showDeleteCategoryDialog

    // Create an instance of a DeleteCategoryDialogFragment and show it
    fun showDeleteCategoryDialog(view: View, categoryId: String) {
        val activity = itemView.context as? MainActivity
        val dialog = DeleteCategoryDialogFragment.newInstance(categoryId)
        dialog.show(activity?.supportFragmentManager, "DeleteCategoryDialog")
    }
    

Upvotes: 0

Kingfisher Phuoc
Kingfisher Phuoc

Reputation: 8200

You can not refer to your MainActivity like your code above. You have to cast the context of your ViewHolder as MainActivity before using it:

val activity =  itemView.context as? MainActivity
// then you can show your dialog with activity?.supportFragmentManager

Upvotes: 8

Massita
Massita

Reputation: 309

My recommendation is to create a callback to this action and implement this callback on your MainActivity and create the dialog direct on your activity.

interface ClickListener {
    fun onLongClickListener(categoryId: Int)
}

then

class CategoryHolder(val customView: View, var category: Category? = null, var mListener: ClickListener?)

...
customView.setOnLongClickListener({
      mListener?.onLongClickListener(categoryId)
      ...
}

and on your MainActivity:

 class MainActivity : AppCompatActivity, ClickListener {

    override fun onLongClickListener(categoryId: Int) {
     // Create your dialog
    }


    ...
        /* when creating your adapter you need to pass the listener to
         * adapter, so it can be used on your viewholder
         * mElements are the category elements, 'this' is the impl of
         * the adapter that was implemented here
        */
        mAdapter = CategoryAdapter(mElements, this)
 }

on your Adapter:

class CategoryAdapter(var mElements: List<Category>, var mListener: ClickListener) : RecyclerView.Adapter<> ...

     // When creating your viewHolder
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryHolder {
        return CategoryHolder(LayoutInflater.from(parent.context) 
            .inflate(R.layout.category_row, parent, false), listener)
}

Upvotes: 0

Related Questions