【问题标题】:Recycler View Callback to activityRecycler View 活动回调
【发布时间】:2020-05-14 16:05:33
【问题描述】:

我正在尝试为单个回收器视图项实现单击侦听器,并从我的活动中使用单击的数据运行方法(单个借用者)。

如何处理?我是 kotlin 的新手,所以一步一步的指导会很有帮助:)

谢谢!

MainActivity:

val db by lazy { Database.getInstance(applicationContext).database }

fun startDebtActivity() {
    val intent = Intent(this, AddDebtActivity::class.java)
    startActivity(intent)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    addDebtBtn.setOnClickListener {
        startDebtActivity()
    }

    thread {
        var borrowers = db.borrowers()
            .getAll()

        runOnUiThread {
            val debtsSum = borrowers.sumByDouble { it.debt }

            // update sum of debts
            summary.text = debtsSum?.toBigDecimal().setScale(2, 2).toString()
            // update item list
            recycler.apply {
                layoutManager = LinearLayoutManager(this@MainActivity)
                adapter = BorrowersListAdapter(borrowers)
            }
        }
    }
}

适配器:

class BorrowersListVh(view: View): RecyclerView.ViewHolder(view) {
    fun refreshData(borrower: Borrower) {
        itemView.borrowersListName.text = borrower.name
        itemView.borrowersLisDebt.text = borrower.debt.toString()

        itemView.setOnClickListener {
            Log.e("info", "Clicked")
        }
    }

    public interface BorrowerClickCallbacks {
        fun onItemClick(position: Int)
    }
}

class BorrowersListAdapter(private val dane: List<Borrower>) :  RecyclerView.Adapter<BorrowersListVh>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BorrowersListVh {
        return BorrowersListVh (
            LayoutInflater.from(parent.context).inflate(R.layout.borrowers_list_item, parent,false)
        )
    }

    override fun getItemCount(): Int = dane.size

    override fun onBindViewHolder(holder: BorrowersListVh, position: Int) {
        val borrower: Borrower = dane[position]
        holder.refreshData(borrower)

        // add notify
    }
}

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    1) 这里的答案适用于 Kotlin 和 Java:

    How to implement click listener callback

    2) 仅限 Kotlin(Lambda):

    在您的适配器中: 添加一个名为 listener 的属性,它是您从活动或片段传递的 lambda:

    class MyAdapter(private val listener: (position: Int) -> Unit) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
    
        ...
    
        inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
    
            init {
                itemView.setOnClickListener(this)
            }
    
            override fun onClick(v: View?) {
                listener.invoke(adapterPosition)
                //or listener(adapterPosition)
            }
        }
    
    }
    

    在你的 Activity/Fragment onCreate() 设置 recyclerview 的布局管理器后:

    recyclerView.adapter = MyAdapter { position ->
        //Do anything you like when some item gets click in your adapter you 
        //can use the position
    }
    

    小心使用内部类,因为它们可能会导致您的应用出现内存泄漏,为了更安全,您可以改用嵌套类。

    【讨论】:

      【解决方案2】:

      您可以通过向您的Borrower 添加一个回调函数来轻松做到这一点。

      给定类型:

      // UI stands for User Interface
      data class BorrowerUI(val borrower: Borrower, val onClick: (Borrower) -> Unit)
      

      然后将您的RecyclerView.Adapter 更改为接收List&lt;BorrowerUI&gt; 而不是List&lt;Borrower&gt;

      之后稍微更改一下您的 refreshData 实现:

      class BorrowersListVh(view: View): RecyclerView.ViewHolder(view) {
          fun refreshData(borrowerUI: BorrowerUI) {
              itemView.borrowersListName.text = borrower.name
              itemView.borrowersLisDebt.text = borrower.debt.toString()
      
              itemView.setOnClickListener {
                  Log.e("info", "Clicked")
                  borrowerUI.onClick(borrowerUI.borrower)
              }
          }
      }
      

      最后在您的Activity 中创建RecyclerView.Adapter

      class YourActivity: AppCompatActivity() {
      
      
           override fun onCreate(savedInstanceState: Bundle?) {
               super.onCreate(savedInstanceState)
               thread {
                    var borrowers = 
                        db.borrowers()
                           .getAll()
                           .map { BorrowerUI(it) { onBorrowerClick(it) } }
      
                    runOnUiThread {
                        val debtsSum = borrowers.sumByDouble { it.debt }
      
                        // update sum of debts
                        summary.text = debtsSum?.toBigDecimal().setScale(2, 2).toString()
                        // update item list
                       recycler.apply {
                           layoutManager = LinearLayoutManager(this@MainActivity)
                           adapter = BorrowersListAdapter(borrowers)
                       }
                     }
               }
           }
      
           fun onBorrowerClick(borrower: Borrower) {
               // Create a toast?
           }
      }
      

      【讨论】:

        【解决方案3】:

        为您的适配器构造函数提供一个附加属性,用于响应被点击的借款人的回调:

        class BorrowersListAdapter(private val dane: List<Borrower>, val onItemClicked: (Borrower) -> Unit) //...
        

        那么在绑定views的时候,你可以在item view上设置一个监听器来调用与新关联的Borrower的回调:

        override fun onBindViewHolder(holder: BorrowersListVh, position: Int) {
            val borrower: Borrower = dane[position]
            holder.refreshData(borrower)
            holder.itemView.setOnClickListener {
                onItemClicked(borrower)
            }
        }
        

        然后在你的Activity中,你可以创建一个匹配回调函数签名的函数。名字无关紧要。

        fun onBorrowerClick(borrower: Borrower) {
            Log.i("borrower clicked", borrower.toString())
        }
        

        当你实例化适配器时,将此函数作为回调传递给构造函数。

        adapter = BorrowersListAdapter(borrowers, ::onBorrowerClick)
        

        旁注,您应该使用lifecycleScope 来启动协程,而不是像您一样直接使用线程,这样您就不会将 Activity 泄漏到后台线程:

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        
            addDebtBtn.setOnClickListener {
                startDebtActivity()
            }
        
            lifecycleScope.launch {
                val borrowers = withContext(Dispatchers.IO) {
                    db.borrowers()
                        .getAll()
                }
        
                val debtsSum = borrowers.sumByDouble { it.debt }
        
                // update sum of debts
                summary.text = debtsSum?.toBigDecimal().setScale(2, 2).toString()
                // update item list
                recycler.apply {
                    layoutManager = LinearLayoutManager(this@MainActivity)
                    adapter = BorrowersListAdapter(borrowers, ::onBorrowerClick)
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-12-22
          • 1970-01-01
          • 1970-01-01
          • 2018-02-11
          • 1970-01-01
          • 1970-01-01
          • 2018-06-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多