问题
I'm trying to post an EventBus event from an recycler item view class and subscribe to it in the same class so that the event is grabbed by ALL the recycler items.
Now in more detail:
I have a RecyclerView where each item (FriendListItem.kt) has a context menu. Only one context menu should be shown at a time. That means that I need to close another item's context menu if its visible.
I chose to use the org.greenrobot.eventbus
which we already widely used in our app. In the item class, when the menu is to be shown, I post an event, and the grab it in the same class. I thought that this way all the items will respond and dismiss their (possibly visible) menus, but the event Subscriber doesn't grab anything.
I'll just add that the containing fragment registers and unregisters the EventBus as it should because it works fine in another event.
The problem here might be that the event should be grabbed in a recycler item view, which manifests in multiple items. Could that be it?
Here is the item:
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()
}
}
Updated solution:
Registered the EventBus locally in the init
clause:
...
init {
View.inflate(context, R.layout.friends_list_item, this)
EventBus.getDefault().register(this@FriendsListItem)
}
...
Unregistered the EventBus in the onDetachedFromWindow
event:
...
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
EventBus.getDefault().unregister(this@FriendsListItem)
}
...
回答1:
Try this. It happened with me for kotlin Int, it might resolve your issue
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FriendsListResetOtherMenus?) {
if (menu != null && !menu!!.isShowing)
menu!!.dismiss()
}
回答2:
I worked with EventBus very little, prefer 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
For sending event:
RxBus.send(NeedToUpdateEvent())
For subscribing to event:
RxBus.observeEvent(NeedToUpdateEvent::class.java)
.subscribe { / some action / }
You can try this
来源:https://stackoverflow.com/questions/51378699/trying-to-impact-recyclerview-items-via-eventbus