正在学习Kotlin,我想实现适配器上的界面,单击项目时将通知活动。什么都没有,我需要您的帮助。
如果我写Java,我会这样写:(界面:OnAnimalClickListener
):
适配器:
public class PackContentAdapter extends RecyclerView.Adapter<PackContentAdapter.ViewHolder> {
private Context context;
private OnAnimalClickListener onAnimalClickListener;
...
void setOnAnimalClickListener(OnAnimalClickListener onAnimalClickListener) {
this.onAnimalClickListener = onAnimalClickListener;
}
...
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
holder.bind(item);
}
...
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
...
ViewHolder(View view) {
super(view);
...
}
void bind(Item item) {
...
}
@Override
public void onClick(View v) {
onAnimalClickListener.onAnimalClicked();
}
}
public interface OnAnimalClickListener {
void onAnimalClicked();
}
}
活动:
contentAdapter.setOnAnimalClickListener(() -> //doSomething);
这是我在Kotlin上写的(名称更改):
适配器:
class PacksAdapter : RecyclerView.Adapter<PacksAdapter.ViewHolder>() {
var onPackClickListener: OnPackClickListener? = null
set(value) {
field = value
}
var packList: ArrayList<Animal> = ArrayList()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.cell_animalpack_4, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(packList[0], context)
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view),View.OnClickListener {
...
fun bind(pack: AnimalPackFull, context: Context) {
...
}
override fun onClick(v: View?) {
onPackClickListener.
}
}
interface OnPackClickListener {
fun onPackClicked(packId: Int)
}
}
活动:
(recycler_packs.adapter as PacksAdapter).onPackClickListener = PacksAdapter.OnPackClickListener()
我的问题:
1)我特别没有在这里完成代码:
override fun onClick(v: View?) {
onPackClickListener.
}
由于我没有从onClick看到我的onPackClickListener
,因此IDE将其写为Unresolved
。为什么?
2)我在活动中遇到错误:
https://jsfiddle.net/o3016bh7/
我能理解,我做错了什么?
答案 0 :(得分:0)
仅当您将嵌套类声明为onPackClickListener
类(请参阅:https://kotlinlang.org/docs/reference/nested-classes.html)时,您才会看到inner
。
但是,我建议将侦听器作为参数传递给ViewHolder
类,并调用该参数,如下所示:
inner class ViewHolder(view: View, itemClickListener: OnPackClickListener?) : RecyclerView.ViewHolder(view), View.OnClickListener {
fun bind(pack: AnimalPackFull, context: Context) { ... }
override fun onClick(v: View?) {
onPackClickListener?.onPackClicked(...)
}
}
另一个问题是,您必须通过实现该接口来创建该接口,因为您不能只是创建该接口的一个实例:
val listener = object : OnPackClickListener {
override fun onPackClicked(packId: Int) {
TODO("not implemented")
}
}
这里的建议。关于Kotlin的一件好事是,您可以将单方法接口切换为lambda(请参见:https://kotlinlang.org/docs/reference/lambdas.html)。 可以将代码重构为如下形式:
class PacksAdapter : RecyclerView.Adapter<PacksAdapter.ViewHolder>() {
var onPackClickListener: ((Int) ->Unit)? = null
set(value) {
field = value
}
var packList: ArrayList<Animal> = ArrayList()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.cell_animalpack_4, parent, false), onPackClickListener)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(packList[0], context)
}
class ViewHolder(view: View, private val itemClickListener: ((Int) ->Unit)?) : RecyclerView.ViewHolder(view), View.OnClickListener {
fun bind(pack: AnimalPackFull, context: Context) { ... }
override fun onClick(v: View?) {
itemClickListener?.invoke(...)
}
}
}
答案 1 :(得分:0)
使用kotlin回调更容易:
在适配器中:
class LEventsAdapter(
private val items: MutableList<EventDetailItem> = ArrayList(),
private val callback: (id: String, distance: String) -> Unit
) : RecyclerView.Adapter<LEventsAdapter.LEventsViewHolder>() {
override fun getItemCount(): Int = items.size
...
在观看者的onclick通话中:callback.invoke(id, distance)
然后在您的活动中实现您的回调:
recView.adapter = LEventsAdapter(items, callback = { id, distance ->
//your code here
})