Невозможно присвоить новое значение простому Singleton, используя onClickeListener для RecyclerView - PullRequest
0 голосов
/ 26 февраля 2019

Я пытаюсь создать приложение чата в стиле Slack, следуя учебному пособию в курсе, который я беру в Интернете.

В учебном пособии инструктор использует ListView и метод OnItemClickListener, но я пытаюсьсделайте это с видом переработчика, и я застрял с onClickListener в адаптере.

Я пытался найти ответы на другие вопросы, но не смог найти тот, который решает мою проблему.Самыми близкими были это и это

Мои две проблемы:
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 голосов
/ 26 февраля 2019
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)
    }
}

Таким образом, вы можете установитьItemClickListener на адаптер в вашей деятельности и получить обратный вызов из вашего recyclerView.Вы не должны устанавливать слушателя в методе onBind (), так как он будет вызван больше, чем количество ваших элементов.

0 голосов
/ 26 февраля 2019

Вы можете переписать переменную 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
}

Альтернативное решение заключается в использовании Observable утилит, таких как LiveData, поэтому вам не стоит беспокоиться о жизненном цикле Android.подробнее:

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

Чтобы изменить значение внутри вашего адаптера, просто вызовите:

ChannelName.activeChannel.value = channels[position]

А внутри вашей деятельности Observe переменную, вызвав:

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