这一切都很复杂,我希望我能很好地解释。因此,我正在使用recyclerview以卡片形式显示用户配置文件列表。每张卡包含2个用于执行不同操作的按钮。现在,这些按钮需要在单击时观察ViewModel内部的LiveData对象(我正在使用MVVM,Android体系结构组件和Kotlin扩展)。一个按钮特别需要根据某种条件观察不同的实时数据。这就是为什么我创建了一个带有条件并返回合适的OnClickListener
的函数的原因。我将其传递给recyclerview适配器。
现在的问题是我在多个片段中使用相同的RecyclerView。当我在编写函数的同一片段中使用recyclerview时,一切工作正常。我在其他任何地方都收到如下错误:
java.lang.IllegalStateException: Fragment HomeFragment{1ef5330} (b299012d-c9c2-427f-8387-a7888289701b)} not attached to an activity.
at androidx.fragment.app.Fragment.requireActivity(Fragment.java:833)
at
com.halalrishtey.HomeFragment$$special$$inlined$activityViewModels$2.invoke(FragmentViewModelLazy.kt:80)
at com.halalrishtey.HomeFragment$$special$$inlined$activityViewModels$2.invoke(Unknown Source:0)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:52)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
at com.halalrishtey.HomeFragment.getUserVM(Unknown Source:7)
at com.halalrishtey.HomeFragment.access$getUserVM$p(HomeFragment.kt:25)
at com.halalrishtey.HomeFragment$genInterestBtnListener$1.onClick(HomeFragment.kt:65)
at android.view.View.performClick(View.java:7125)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
创建OnClickListener的函数如下所示:
fun genInterestBtnListener(
condition: Boolean,
v: View
): View.OnClickListener {
return View.OnClickListener {
if (!condition) {
userVM.initInterest().observe(viewLifecycleOwner, Observer { msg ->
Toast.makeText(context, msg, Toast.LENGTH_SHORT)
.show()
//More code here
})
} else {
userVM.removeInterest().observe(viewLifecycleOwner, Observer { msg ->
Toast.makeText(context, msg, Toast.LENGTH_SHORT)
.show()
})
}
}
}
我无法观察适配器内部的情况,因此无需重复执行代码的最佳解决方案是什么?
更新:我这样声明userVM:
private val userVM: UserViewModel by activityViewModels()
也这是我的适配器代码:
class CardDataRVAdapter(private var items: List<ProfileCardData>) :
RecyclerView.Adapter<CardDataRVAdapter.CardDataViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardDataViewHolder {
val inflatedView =
LayoutInflater.from(parent.context).inflate(R.layout.profile_card, parent, false)
return CardDataViewHolder(inflatedView)
}
override fun onBindViewHolder(holder: CardDataViewHolder, position: Int) {
val card = items[position]
holder.bindCard(card)
}
override fun getItemCount() = items.size
class CardDataViewHolder constructor(
v: View
) : RecyclerView.ViewHolder(v), View.OnClickListener {
private var view: View = v
private var cardData: ProfileCardData? = null
init {
v.setOnClickListener(this)
}
override fun onClick(p0: View?) {
//TODO: Implement a proper onClickListener
Toast.makeText(
p0?.context,
"${p0?.cardTitleTextView?.text} Card was clicked",
Toast.LENGTH_SHORT
).show()
}
companion object {
private val KEY = "CARD"
}
fun bindCard(card: ProfileCardData) {
this.cardData = card
if (card.isUserShortlisted) {
view.showInterestBtn.setIconResource(R.drawable.ic_favorite)
} else {
view.showInterestBtn.setIconResource(R.drawable.ic_favorite_border)
}
if (card.data.photoUrl.length > 5) {
Picasso.get().load(card.data.photoUrl)
.into(view.cardImageView)
Picasso.get().load(card.data.photoUrl)
.into(view.cardAvatarImageView)
}
view.cardTitleTextView.text = card.data.displayName
view.cardSubtitleTextView.text = "${card.data.age} - ${card.data.height}"
view.showInterestBtn.setOnClickListener(card.showBtnInterestListener)
view.sendMessageBtn.setOnClickListener(card.messageBtnListener)
}
}
}
答案 0 :(得分:0)
根据我的理解,应该在创建ViewModel类实例的片段/活动中观察每个getTableDestination()
。
我认为出现此问题是因为您试图观察LiveData所创建的片段之外的片段。
您可以使用tableNameAttr
在片段/活动之外观察LiveData,但还需要调用LiveData
以避免内存泄漏
cmiiw
答案 1 :(得分:0)
我认为您的问题是因为您在view.
函数中使用了bindCard()
。
您的课程中的showBtnInterestListener是吗?您可以将其移至Adapter
,因为Adapter
更了解监听器而不是data class
您能否尝试这样更改您的Adapter
:
您在类中声明要与之交互的对象,然后在绑定中调用它们。
class CardDataViewHolder constructor(
v: View
) : RecyclerView.ViewHolder(v), View.OnClickListener {
private var view: View = v
private var cardData: ProfileCardData? = null
val showInterestBtn = view.findViewById(R.id.show_interest)
val sendMessageBtn = view.findViewById(R.id.message_btn)
val title = view.findViewById(R.id.card_title)
val subtitle = view.findViewById(R.id.card_subtitle)
companion object {
private val KEY = "CARD"
}
fun bindCard(card: ProfileCardData) {
this.cardData = card
if (card.isUserShortlisted) {
showInterestBtn.setIconResource(R.drawable.ic_favorite)
} else {
showInterestBtn.setIconResource(R.drawable.ic_favorite_border)
}
if (card.data.photoUrl.length > 5) {
Picasso.get().load(card.data.photoUrl)
.into(view.cardImageView)
Picasso.get().load(card.data.photoUrl)
.into(view.cardAvatarImageView)
}
title.text = card.data.displayName
subtitle.text = "${card.data.age} - ${card.data.height}"
showInterestBtn.setOnClickListener(card.showBtnInterestListener)
sendMessageBtn.setOnClickListener(card.messageBtnListener)
}
}