适配器中的接口

时间:2019-03-26 13:10:52

标签: android kotlin

正在学习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/

我能理解,我做错了什么?

2 个答案:

答案 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
})