【问题标题】:Kotlin: How do I call a DialogFragment from within an Adapter class?Kotlin:如何从 Adapter 类中调用 DialogFragment?
【发布时间】:2018-04-10 14:20:35
【问题描述】:

我有一个处理 RecyclerView 的 MainAdapter.kt 类。在其 Holder 类中,我使用 OnLongClickListener 调用函数 deleteCategory(categoryId) 来删除我的 Firebase 数据库中的条目。这完美地工作:

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")
    }
}

但我宁愿调用 DialogFragment 类中的函数而不是 deleteCategory(id) 函数,如下所示:

  // 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")
  }

这给了我一个“未解决的引用:@MainActivity”错误。 我该如何解决这个问题?有没有办法在我的 MainActivity 中获取 categoryId(字符串类型)?这将允许我将函数 showDeleteCategoryDialog 移动到 MainActivity 并解决问题。

【问题讨论】:

  • 你在哪里定义showDeleteCategoryDialog()函数?在适配器内部?
  • 是的,因为我需要为 categoryId 提供一个值,这是我在 CategoryHolder 的绑定函数中检索到的字符串。 showDeleteCategoryDialog() 函数在 MainActivity 中定义并提供“假” categoryId 时工作正常。

标签: android firebase kotlin adapter dialogfragment


【解决方案1】:

您不能像上面的代码那样引用您的MainActivity。在使用之前,您必须将 ViewHoldercontext 转换为 MainActivity

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

【讨论】:

    【解决方案2】:

    我的建议是为此操作创建一个回调,并在您的 MainActivity 上实现此回调,并直接在您的 Activity 上创建对话框。

    interface ClickListener {
        fun onLongClickListener(categoryId: Int)
    }
    

    然后

    class CategoryHolder(val customView: View, var category: Category? = null, var mListener: ClickListener?)
    
    ...
    customView.setOnLongClickListener({
          mListener?.onLongClickListener(categoryId)
          ...
    }
    

    在您的 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)
     }
    

    在您的适配器上:

    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)
    }
    

    【讨论】:

    • 这在我的 onCreateViewHolder 函数中给我一个错误:“没有为参数 mListener 传递值”
    • 在 MainActivity 中实现了这个监听器后,你需要在 ViewHolder 构造函数中将 Activity 作为一个新参数传递... 现在你需要像val holder = CategoryHolder(customView, category, listener)一样创建你的 ViewHolder
    • 现在你需要在创建viewholder时传递监听器...override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryHolder { return CategoryHolder(LayoutInflater.from(parent.context) .inflate(R.layout.category_row, parent, false), listener) } 你可以在你的适配器上创建这个监听器,并在创建时将监听器传递给ViewHolder
    • @CEOtech4lifeapps 我已经更新了我的答案,现在更容易了吗? :D
    • 恐怕这无济于事。我的 MainAdapter 属于 FirebaseRecyclerAdapter 类型,它不适用于包含元素的列表,并且 categoryId 属于 String 类型,而不是 Int。
    【解决方案3】:

    以下是详细的解决方法:

    1. 在类 CategoryHolder 中

      customView.setOnLongClickListener(
          {
            showDeleteCategoryDialog(it, categoryId)
            true
          } 
      )
      
    2. 在函数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")
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-17
      • 2021-08-24
      • 2022-08-24
      • 1970-01-01
      • 2021-11-14
      • 2013-10-15
      相关资源
      最近更新 更多