尽管已初始化,但是lateinit属性尚未在Fragment中初始化

时间:2020-07-30 20:23:26

标签: android kotlin google-cloud-firestore

礼物, 我有一个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)
}
}

3 个答案:

答案 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)

在这种情况下,我实现的方法也可以正常工作。