一、 背景
-
截止本文撰写时,CymChad/BaseRecyclerViewAdapterHelper 为 3.0.6 版本,commit id 为 2813dd1dac57d2e0309c2315f8569e455735c343,且 Demo 处于编译不过的状态(Java 实现了 Kotlin 含默认实现方法的接口,需要使用 @JvmDefault 注解)。
-
用过的童鞋应该知道,BaseQuickAdapter 中有个 setOnItemClickListener(OnItemClickListener) 的方法,用于设置 item 的点击回调,但是在回到的地方却需要强制类型转换。
究其原因,是因为 OnItemClickListener 定义在了一个单独的文件里,并且没有指定泛型。
public interface OnItemClickListener {
void onItemClick(@NonNull BaseQuickAdapter<?,?> adapter, @NonNull View view, int position);
}
- 看官方的示例代码
class HomeActivity : AppCompatActivity(), OnItemClickListener {
private lateinit var binding: ActivityHomeBinding
/**
* RV适配器
*/
private val homeAdapter by lazy {
HomeAdapter(homeItemData).apply {
animationEnable = true
val top = layoutInflater.inflate(R.layout.top_view, binding.recyclerView, false)
addHeaderView(top)
setOnItemClickListener(this@HomeActivity)
}
}
override fun onItemClick(adapter: BaseQuickAdapter<*, *>, view: View, position: Int) {
// 这里用到了强制类型转换
val item = adapter.data[position] as HomeEntity
if (!item.isHeader) {
startActivity(Intent(this@HomeActivity, item.activity))
}
}
...
}
二、解决方式1:传递泛型给 OnItemClickListener
- 给 OnItemClickListener 加上泛型
public interface OnItemClickListener<T, VH extends BaseViewHolder> {
void onItemClick(@NonNull BaseQuickAdapter<T, VH> adapter, @NonNull View view, int position);
}
- BaseQuickAdapter 中代码也需要修改
修改前:
abstract class BaseQuickAdapter<T, VH : BaseViewHolder>
@JvmOverloads constructor(@LayoutRes private val layoutResId: Int,
data: MutableList<T>? = null)
: RecyclerView.Adapter<VH>() {
private var mOnItemClickListener: OnItemClickListener? = null
fun setOnItemClickListener(listener: OnItemClickListener?) {
this.mOnItemClickListener = listener
}
fun getOnItemClickListener(): OnItemClickListener? = mOnItemClickListener
}
修改后:
abstract class BaseQuickAdapter<T, VH : BaseViewHolder>
@JvmOverloads constructor(@LayoutRes private val layoutResId: Int,
data: MutableList<T>? = null)
: RecyclerView.Adapter<VH>() {
private var mOnItemClickListener: OnItemClickListener<T, VH>? = null
fun setOnItemClickListener(listener: OnItemClickListener<T, VH>?) {
this.mOnItemClickListener = listener
}
fun getOnItemClickListener(): OnItemClickListener<T, VH>? = mOnItemClickListener
}
- 此时 HomeActivity 中则可以不用强制类型转换了
class HomeActivity : AppCompatActivity(), OnItemClickListener<HomeEntity, BaseViewHolder> {
private lateinit var binding: ActivityHomeBinding
/**
* RV适配器
*/
private val homeAdapter by lazy {
HomeAdapter(homeItemData).apply {
animationEnable = true
val top = layoutInflater.inflate(R.layout.top_view, binding.recyclerView, false)
addHeaderView(top)
setOnItemClickListener(this@HomeActivity)
}
}
override fun onItemClick(adapter: BaseQuickAdapter<HomeEntity, BaseViewHolder>, view: View, position: Int) {
// 不再需要强制类型转换
// val item = adapter.data[position] as HomeEntity
val item = adapter.data[position]
if (!item.isHeader) {
startActivity(Intent(this@HomeActivity, item.activity))
}
}
...
}
也可以直接以 Lambda 的形式来写:
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
/**
* RV适配器
*/
private val homeAdapter by lazy {
HomeAdapter(homeItemData).apply {
animationEnable = true
val top = layoutInflater.inflate(R.layout.top_view, binding.recyclerView, false)
addHeaderView(top)
setOnItemClickListener { adapter, view, position ->
// 不再需要强制类型转换
// val item = adapter.data[position] as HomeEntity
val item = adapter.data[position]
if (!item.isHeader) {
startActivity(Intent(this@HomeActivity, item.activity))
}
}
}
}
...
}
三、解决方式2:不使用 OnItemClickListener 类
- 不再使用 OnItemClickListener 类,而是以 Lambda 的形式来定义 BaseQuickAdapter#mOnItemClickListener
修改前:
abstract class BaseQuickAdapter<T, VH : BaseViewHolder>
@JvmOverloads constructor(@LayoutRes private val layoutResId: Int,
data: MutableList<T>? = null)
: RecyclerView.Adapter<VH>() {
private var mOnItemClickListener: OnItemClickListener? = null
protected open fun setOnItemClick(v: View, position: Int) {
// 通过这里回调出去
mOnItemClickListener?.onItemClick(this, v, position)
}
fun setOnItemClickListener(listener: OnItemClickListener?) {
this.mOnItemClickListener = listener
}
fun getOnItemClickListener(): OnItemClickListener? = mOnItemClickListener
}
修改后:
abstract class BaseQuickAdapter<T, VH : BaseViewHolder>
@JvmOverloads constructor(@LayoutRes private val layoutResId: Int,
data: MutableList<T>? = null)
: RecyclerView.Adapter<VH>() {
private var mOnItemClickListener: ((BaseQuickAdapter<T, VH>, View, Int) -> Unit)? = null
protected open fun setOnItemClick(v: View, position: Int) {
// 通过这里回调出去
mOnItemClickListener?.invoke(this, v, position)
}
fun setOnItemClickListener(listener: ((BaseQuickAdapter<T, VH>, View, Int) -> Unit)?) {
this.mOnItemClickListener = listener
}
fun getOnItemClickListener() = mOnItemClickListener
}
- 此时 HomeActivity 中则可以不用强制类型转换了
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
/**
* RV适配器
*/
private val homeAdapter by lazy {
HomeAdapter(homeItemData).apply {
animationEnable = true
val top = layoutInflater.inflate(R.layout.top_view, binding.recyclerView, false)
addHeaderView(top)
setOnItemClickListener { adapter, view, position ->
// 不再需要强制类型转换
// val item = adapter.data[position] as HomeEntity
val item = adapter.data[position]
if (!item.isHeader) {
startActivity(Intent(this@HomeActivity, item.activity))
}
}
}
}
...
}
当然,也可以在类上声明实现这个接口:
class HomeActivity : AppCompatActivity(),
(BaseQuickAdapter<HomeEntity, BaseViewHolder>, View, Int) -> Unit {
private lateinit var binding: ActivityHomeBinding
/**
* RV适配器
*/
private val homeAdapter by lazy {
HomeAdapter(homeItemData).apply {
animationEnable = true
val top = layoutInflater.inflate(R.layout.top_view, binding.recyclerView, false)
addHeaderView(top)
setOnItemClickListener(this@HomeActivity)
}
}
override fun invoke(
adapter: BaseQuickAdapter<HomeEntity, BaseViewHolder>,
view: View,
position: Int
) {
// 不再需要强制类型转换
// val item = adapter.data[position] as HomeEntity
val item = adapter.data[position]
if (!item.isHeader) {
startActivity(Intent(this@HomeActivity, item.activity))
}
}
...
}
网友评论