礼物, 我有一个FirestoreRecyclerAdapter,可以从Firestore中提取数据。在提取数据之前,我想显示一个方便工作的skeletonView。为了在提取数据时通知Fragment,我使用了一个侦听器。但是,当我在Fragment中重写此侦听器接口的方法时,由于某种原因,我为我的recyclerView收到了“ kotlin.UninitializedPropertyAccessException:lateinit属性rvShops尚未初始化”,即使它们在触发接口方法时已初始化。我的代码段如下:
class ShopsFragment : Fragment(), ShopsLoadedListener {
companion object {
fun newInstance(): ShopsFragment {
return ShopsFragment()
}
}
private lateinit var colRefShops: CollectionReference
private lateinit var shopAdapter: ShopAdapter
private lateinit var v: View
private lateinit var b: FragmentShopsBinding
private lateinit var skeleton: Skeleton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
(activity as MainActivity).tabLayoutShops.visibility = View.GONE
colRefShops = FirebaseFirestore.getInstance().collection(DB_SHOPS)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
v = inflater.inflate(R.layout.fragment_shops, container, false)
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initRecyclerView()
}
override fun onStart() {
super.onStart()
shopAdapter.startListening()
}
private fun initRecyclerView() {
rvShops?.layoutManager = GridLayoutManager(v.context, 2)
skeleton = skelOutShops
skeleton = rvShops.applySkeleton(R.layout.item_shop, 10)
skeleton.showSkeleton()
val q: Query = colRefShops.orderBy(WEIGHT)
val options: FirestoreRecyclerOptions<ModelShop> =
FirestoreRecyclerOptions.Builder<ModelShop>()
.setQuery(q, ModelShop::class.java)
.build()
shopAdapter = ShopAdapter(options, shopsLoadedListener = newInstance())
}
override fun onStop() {
super.onStop()
shopAdapter.stopListening()
}
override fun onShopsLoaded(i: Int) {
Log.d("dataComes", "Data = $i")
rvShops.adapter = shopAdapter //here i get kotlin.UninitializedPropertyAccessException: lateinit property rvShops has not been initialized when this method is fired up
skeleton.showOriginal()
}
}
我的适配器:
class ShopAdapter(options: FirestoreRecyclerOptions<ModelShop>, private var shopsLoadedListener: ShopsLoadedListener)
: FirestoreRecyclerAdapter<ModelShop, ShopAdapter.ShopViewHolder>(options) {
override fun onDataChanged() {
super.onDataChanged()
shopsLoadedListener.onShopsLoaded(5)
}
private var v: View? = null
public interface ShopsLoadedListener{
fun onShopsLoaded(i: Int)
}
class ShopViewHolder(private val b: ItemShopBinding) : RecyclerView.ViewHolder(b.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShopViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val v = layoutInflater.inflate(R.layout.item_shop, parent, false)
val b = ItemShopBinding.inflate(layoutInflater)
Log.d("fire", "ifireincreateviewholder")
return ShopViewHolder(b)
}
override fun onBindViewHolder(vHolder: ShopViewHolder, i: Int, modelShop: ModelShop) {
vHolder.itemView.tvShopName.text = modelShop.displayName
Glide.with(vHolder.itemView.context)
.load(modelShop.logoURL)
.centerCrop()
.into(vHolder.itemView.ivShopLogo)
}
}
答案 0 :(得分:1)
该错误消息告诉您在分配值之前尝试使用skeleton
。几乎可以肯定,在onShopsLoaded
初始化之前调用了initRecyclerView
。您将必须编写代码来检测这种情况并正确处理。
答案 1 :(得分:0)
据我所知,您永远不会将rvShops
分配给任何东西,这会使它未初始化。假设将其设置为lateinit
,那么您就可以使用UninitializedPropertyAccessException
。
解决方案:
在片段的rvShops
中分配onViewCreated(...)
,这样就不会再崩溃了。
答案 2 :(得分:0)
private fun initRecyclerView() {
rvShops?.layoutManager = GridLayoutManager(v.context, 2)
skeleton = skelOutShops
skeleton = rvShops.applySkeleton(R.layout.item_shop, 10)
skeleton.showSkeleton()
val q: Query = colRefShops.orderBy(WEIGHT)
val options: FirestoreRecyclerOptions<ModelShop> =
FirestoreRecyclerOptions.Builder<ModelShop>()
.setQuery(q, ModelShop::class.java)
.build()
shopAdapter = ShopAdapter(options, shopsLoadedListener = newInstance())
}
原来问题出在此函数中,尤其是该行:
shopAdapter = ShopAdapter(options, shopsLoadedListener = newInstance())
创建此侦听器实例的正确方法应该是:
shopAdapter = ShopAdapter(options, this)
在这种情况下,我实现的方法也可以正常工作。