持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
Android开发中回调用的最多的地方,应该属Adapter、各种监听事件和处理数据时的异步调用。如:在Activity/Fragment中响应RecyclerView中的动作,获得从RecyclerView中传递出来的数据,在Dialog外部对内部按钮点击事件的处理等。
什么是回调? 如图:
类A实现了接口C实例instance,接口中的方法可以带有参数和返回值。类B获得instance后,根据情况调用instance的方法。实际调用了类A实现的方法,类A作出响应动作,根据传入参数返回值给类B。即类B通过接口C实例调用了类A实现的接口C方法。
在Java中,接口回调必须要声明一个接口。但在Kotlin中,可以直接使用匿名函数代替接口。但如果接口中有多个函数的话,还是使用接口更方便。
以在Activity中响应RecyclerView点击事件弹出弹窗为例子,Adapter部分代码(类B、接口C):
class AdressBookAdapter : RecyclerView.Adapter<AdressBookAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//TODO......
fun init(model: AdressBookModel) {
//TODO......
itemView.setOnClickListener {
mClickListener?.clickItem(model) //类B调用接口C方法
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.rv_item_adress_book, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.init(data.get(position))
}
override fun getItemCount(): Int = data.size
/**
* data
*/
private val data = arrayListOf<AdressBookModel>()
fun setData(list: List<AdressBookModel>) {
data.clear()
data.addAll(list)
notifyDataSetChanged()
}
/**
* ListenerInterface (接口C)
*/
interface ClickListener {
fun clickItem(modle: AdressBookModel)
}
//接口实例
var mClickListener: ClickListener? = null
}
Activity部分代码(类A):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//类A实现接口C方法
val clickListener=object :AdressBookAdapter.ClickListener{
override fun clickItem(modle: AdressBookModel) {
showAdressDlg(modle) //弹出弹窗
}
}
rv.run {
layoutManager =
LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false)
adapter = this@MainActivity.adapter.apply {
this.mClickListener=clickListener //类A将接口C实例传递给类B
}
}
}
这是接口回调的实现。如果使用匿名函数,该如何实现呢?还是举同样的例子。
Adapter部分代码:
class AdressBookAdapter : RecyclerView.Adapter<AdressBookAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//TODO......
fun init(model: AdressBookModel) {
//TODO......
itemView.setOnClickListener {
clickItem(model) //调用匿名函数
}
}
}
//重写RecyclerView.Adapter函数和数据设置部分没有变化
//将监听接口替换为匿名函数
//声明一个匿名函数,带一个AdressBookModel参数,返回值为Unit,函数体为空
var clickItem: (AdressBookModel) -> Unit = {}
}
Activity部分:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
rv.run {
layoutManager =
LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false)
adapter = this@MainActivity.adapter.apply {
clickItem = { //实现Adapter的匿名函数
showAdressDlg(it)
}
}
}
getData()
}
以上是回调的两种实现方式:通过接口实现和通过匿名函数实现。 通过匿名函数实现比通过接口实现更加方便,代码更加简洁。
掌握接口回调的思想,能够解决UI组件间交互的大部分问题。