试图通过 EventBus 影响 RecyclerView 项目

Trying to impact RecyclerView items via EventBus

我正在尝试 post 来自回收站项目视图的 EventBus 事件 class 并在同一个 class 中订阅它,以便所有回收站都能获取该事件项目。

现在更详细:

我有一个 RecyclerView,其中每个项目 (FriendListItem.kt) 都有一个上下文菜单。一次只能显示一个上下文菜单。这意味着我需要关闭另一个项目的上下文菜单(如果它可见)。

我选择使用我们已经在我们的应用程序中广泛使用的 org.greenrobot.eventbus。在项目class中,当要显示菜单时,我post一个事件,并在同一个class中抓取它。我认为这样所有项目都会响应并关闭它们的(可能可见的)菜单,但是事件订阅者不会获取任何东西。

我将补充一点,包含的片段会按应有的方式注册和注销 EventBus,因为它在另一个事件中工作正常。

这里的问题可能是应该在回收站项目视图中抓取事件,该视图显示在多个项目中。会不会是这样?

这是项目:

package com.myapp.android.common.social.friends

import android.content.Context
import android.text.Spanned
import android.view.View
import android.view.View.OnClickListener
import android.widget.ImageView
import android.widget.LinearLayout
import com.myapp.android.common.R
import com.myapp.android.common.database.room.entities.User
import com.myapp.android.common.generic.coachmark.BubbleCoachMark
import com.myapp.android.common.image.ImageSize
import com.myapp.android.common.social.friends.events.FriendsListResetOtherMenus
import kotlinx.android.synthetic.main.friends_list_item.view.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class FriendsListItem(context: Context) : LinearLayout(context) {

    private var user: User? = null
    private var menu: BubbleCoachMark? = null

    init {
        View.inflate(context, R.layout.friends_list_item, this)
    }

    fun updateView(user: User, sp: Spanned?) {
        this.user = user

        // Avatar
        if (user.pictureUrl != "") {
            setUserPicture(user.pictureUrl + "", user.isPremium)
        }

        // Premium
        when {
            user.isPremium -> friendPremium.visibility = View.VISIBLE
            else -> friendPremium.visibility = View.GONE
        }

        // Name
        when (sp) {
            null -> friendName!!.text = user.name
            else -> friendName!!.text = sp
        }

        // Friend Status
        invite.visibility = View.GONE
        action.visibility = View.VISIBLE

        when (user.status) {
            User.Status.friend -> {
                action.setImageResource(R.drawable.ic_friend_options)
                action.setOnClickListener(OnClickListener {
                    EventBus.getDefault().post(FriendsListResetOtherMenus())
                    when (menu) {
                        null -> {
                            menu = BubbleCoachMark(BubbleCoachMark.BubbleCoachMarkBuilder(context, action, FriendsListItemMenu(context)).setShowBelowAnchor(true))
                            menu!!.show()
                        }
                        else -> {
                            if (!menu!!.isShowing)
                                menu!!.show()
                        }
                    }
                })
            }
            User.Status.pending -> {
                action.setImageResource(R.drawable.ic_friend_requested)
            }
            User.Status.nofriend -> {
                action.setImageResource(R.drawable.ic_friend_add)
            }
            else -> {
                invite.visibility = View.VISIBLE
                action.visibility = View.GONE
            }
        }
    }

    fun setUserPicture(pictureUrl: String, isPremium: Boolean) {
        synchronized(this) {
            friendAvatar!!.scaleType = ImageView.ScaleType.CENTER_CROP
            friendAvatar!!.setUserPicture(pictureUrl, isPremium, R.drawable.profile_silhuette_new, ImageSize.thumbnail)
        }
    }

    // The method here is not grabbing the event
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(event: FriendsListResetOtherMenus) {
        if (menu != null && !menu!!.isShowing)
            menu!!.dismiss()
    }
}

更新的解决方案:

init子句中本地注册了EventBus:

...
init {
    View.inflate(context, R.layout.friends_list_item, this)

    EventBus.getDefault().register(this@FriendsListItem)
}
...

取消注册 onDetachedFromWindow 事件中的 EventBus:

...
override fun onDetachedFromWindow() {
    super.onDetachedFromWindow()

    EventBus.getDefault().unregister(this@FriendsListItem)
}
...

试试这个。我遇到了 kotlin Int,它可能会解决你的问题

@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FriendsListResetOtherMenus?) {
    if (menu != null && !menu!!.isShowing)
        menu!!.dismiss()
}

我很少使用 EventBus,更喜欢 RxBus:

object RxBus {

    private val bus = PublishSubject.create<Any>()

    fun send(event: Any) {
        bus.onNext(event)
    }

    fun <T> observeEvent(type: Class<T>): Observable<T> =
        bus.ofType(type)
}

class NeedToUpdateEvent

发送事件:

RxBus.send(NeedToUpdateEvent())

订阅活动:

RxBus.observeEvent(NeedToUpdateEvent::class.java)
        .subscribe { / some action / }

你可以试试这个