有如下常用情景,在某个Adapter我们设置自己的接口回调,将原来的java代码改写之后大概会是这个样子:
class SomeListAdapter(){
var mOnItemClickListener:OnItemClickListener? = null
fun setOnItemClickListener(onItemClickListener : OnItemClickListener){
mOnItemClickListener = onItemClickListener
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
mOnItemClickListener?.onItemClick(article)
}
companion object {
public interface OnItemClickListener{
fun onItemClick(article:DTArticle)
}
}
}
//////////
override fun setAdapter(){
var adapter = SomeListAdapter(context)
adapter.setOnItemClickListener ( object: ArticleListAdapter.Companion.OnItemClickListener {
override fun onItemClick(article: DTArticle) {
SomeDetailActivity.startInstance(context,article.mId)
}
}
)
}
即使你完全不知道kotlin,也很容易理解上面的代码,因为和java实在是太像了。
但是对于kotlin而言,或许我们有更好更简单的方法
class SomeListAdapter(context: Context) : BaseListAdapter<DTArticle>(context) {
lateinit var mOnItemClickListener: (DTArticle) -> Unit
fun setOnItemClickListener(onItemClickListener: (DTArticle) -> Unit) {
mOnItemClickListener = onItemClickListener
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (mOnItemClickListener != null) {
mOnItemClickListener(article)
}
}
companion object {
}
}
//////////////////
override fun setAdapter(){
var adapter = SomeListAdapter(context)
adapter.setOnItemClickListener{
SomeDetailActivity.startInstance(context,it.mId)
}
}
看看我们做了什么?我们抛弃了接口的概念,而是引入了一个新的类型的变量:
(DTArticle) -> Unit
这是一个整体,不可分割,表示入参是DTArticle,返回值为空的一个方法参数,有点类似函数指针的样子嘛。
注意,调用的地方也有所改变,我们需要意识到,这个参数本身就是一个方法。
能不能继续简化?多谢一个setOnItemClickListener感觉在kotlin中是没必要的,所以,我们去掉它吧
class SomeListAdapter(context: Context) : BaseListAdapter<DTArticle>(context) {
lateinit var mOnItemClickListener: (DTArticle) -> Unit
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (mOnItemClickListener != null) {
mOnItemClickListener(article)
}
}
companion object {
}
}
//////////////////
override fun setAdapter(){
var adapter = SomeListAdapter(context)
adapter.mOnItemClickListener = {
SomeDetailActivity.startInstance(context,it.mId)
}
}
这样就看上去很简洁了,并且已经和java代码相去胜远了,但是实际上做的是同一件事情。
对于多参数的接口类型,比如:
lateinit var listener:(pos:Int,a:String)->Unit
会出现一个问题,it到底代指哪个参数?肯定会出现问题,所以对于这种情况,使用时这样的
listener = {pos, a -> Log.d("sss",a+pos) }
我们需要显示的指定参数名!