无法为RecyclerView使用onClickeListener将新值分配给简单的Singleton

时间:2019-02-26 04:35:04

标签: android kotlin android-recyclerview onclicklistener recycler-adapter

我正在按照在线课程中的教程,尝试构建一个类似于Slack的聊天应用程序。

在本教程中,讲师使用的是ListView和OnItemClickListener方法,但是我尝试使用回收站视图进行操作,并且卡在适配器中的onClickListener上。

我试图找到其他问题的答案,但找不到解决我问题的答案。最接近的是thisthis

我的两个问题是:
1.该应用程序的主要活动在屏幕顶部具有一个标题,指出当前处于活动状态的频道。我创建了一个包含“当前通道”的单例,并且标题文本已从该单例中提取。 我很难更改点击时该单例的值。

  1. 主活动在抽屉中的列表视图中还具有所有通道。 单击一个频道时,我试图关闭抽屉,但这也没有发生。

这是我当前的适配器:

class ChannelsAdapter(val context: Context, val channels: ArrayList<Channel>) :
    RecyclerView.Adapter<ChannelsAdapter.Holder>() {


    inner class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val singleChannel = itemView.findViewById<TextView>(R.id.single_channel)

        val mainLayout = LayoutInflater.from(context).inflate(R.layout.activity_main, null)

        fun bindText(textVar: String, context: Context) {
            singleChannel.text = textVar
        }
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.bindText(channels[position].toString(), context)

        holder.itemView.setOnClickListener {

            ChannelName.activeChannel = channels[position]

            holder.mainLayout.drawer_layout.closeDrawer(GravityCompat.START)

        }

    }

    override fun getItemCount(): Int {
        return channels.count()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChannelsAdapter.Holder {

        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.channel_list_layout, parent, false)
        return Holder(view)

    }

}

这是单身人士

object ChannelName {

var activeChannel : Channel? = null

}

2 个答案:

答案 0 :(得分:1)

您可以为setter变量重写activeChanell并调用之前添加的侦听器来通知您的Activity

object ChannelName {
    private val listeners = ArrayList<(Channel?) -> Unit>()

    fun addChannelNameChangedListener(listener: (Channel?) -> Unit) {
        listeners.add(listener)
    }

    fun removeChannelNameChangedListener(listener: (Channel?) -> Unit) {
        listeners.remove(listener)
    }

    var activeChannel: Channel? = null
        set(value) {
            field = value
            listeners.forEach { it.invoke(value) }
        }
}

Activity内添加一个这样的侦听器:

ChannelName.addChannelNameChangedListener { 
    // Do your operation
}

替代解决方案是使用LiveData之类的Observable实用程序,因此您不必再担心Android生命周期:

object ChannelName {
    val activeChannel: MutableLiveData<ChannelName> = MutableLiveData()
}

要更改适配器内部的值,只需调用:

ChannelName.activeChannel.value = channels[position]

在您的活动Observe中,通过调用:

ChannelName.activeChannel.observe(this, Observer { 
    // Do your operation
})

答案 1 :(得分:0)

class ChannelsAdapter(val context: Context, val channels: ArrayList<Channel>) :
        RecyclerView.Adapter<ChannelsAdapter.Holder>() {

    private var itemClickListener: OnItemClickListener? = null

    fun setItemClickListener(itemClickListener: OnItemClickListener) {
        this.itemClickListener = itemClickListener
    }

    interface OnItemClickListener {
        fun onItemClick(position: Int)
    }

    inner class Holder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

        val singleChannel = itemView.findViewById<TextView>(R.id.single_channel)

        val mainLayout = LayoutInflater.from(context).inflate(R.layout.activity_main, null)

        fun bindText(textVar: String, context: Context) {
            singleChannel.text = textVar
        }

        override fun onClick(v: View?) {
            val position = adapterPosition
            itemClickListener?.let {
                if (position != RecyclerView.NO_POSITION) {
                    it.onItemClick(position)
                }
            }
        }
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.bindText(channels[position].toString(), context)
    }

    override fun getItemCount(): Int {
        return channels.count()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChannelsAdapter.Holder {
        val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.channel_list_layout, parent, false)
        return Holder(view)
    }
}

这样,您可以将ItemSetClickListener设置为活动中的适配器,并从recyclerView获取回调。 您不应在onBind()方法中设置侦听器,因为它的调用次数将超过您的项目计数。