0

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(this@MainActivity.supportFragmentManager, 
      "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.

CEO tech4lifeapps
  • 885
  • 1
  • 12
  • 31
  • Where do you define the `showDeleteCategoryDialog()` function? Inside the adapter? – earthw0rmjim Apr 10 '18 at 16:07
  • Yes, because I need to provide a value for categoryId, a String that I retrieve in the bind function of my CategoryHolder. The showDeleteCategoryDialog() function works fine when defined in MainActivity and provided with a 'fake' categoryId. – CEO tech4lifeapps Apr 10 '18 at 16:26

3 Answers3

8

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
Kingfisher Phuoc
  • 8,052
  • 9
  • 46
  • 86
0

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)
}
Massita
  • 309
  • 2
  • 10
  • This gives me an error in my onCreateViewHolder function: "No value passed for parameter mListener" – CEO tech4lifeapps Apr 10 '18 at 15:29
  • After implementing this listener in the MainActivity, you need to pass the activity as a new parameter on the ViewHolder constructor... Now you need to create your ViewHolder like `val holder = CategoryHolder(customView, category, listener)` – Massita Apr 10 '18 at 16:38
  • Now you need to pass the listener when creating the viewholder... `override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryHolder { return CategoryHolder(LayoutInflater.from(parent.context) .inflate(R.layout.category_row, parent, false), listener) } ` You can create this listener on your adapter and pass the listener to the ViewHolder when creating it – Massita Apr 10 '18 at 17:05
  • @CEOtech4lifeapps i've updated my answer, is it easier now? :D – Massita Apr 10 '18 at 17:18
  • I'm afraid, this does not help. My MainAdapter is of type FirebaseRecyclerAdapter that does not work on a list holding elements and categoryId is of type String, not Int. – CEO tech4lifeapps Apr 11 '18 at 04:06
0

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")
    }
    
CEO tech4lifeapps
  • 885
  • 1
  • 12
  • 31