Android 尽管进行了初始化,lateinit属性尚未在片段中初始化
格雷廷斯, 我有一个FirestoreRecyclerAdapter,可以从Firestore中提取数据。在提取数据之前,我想显示一个工作方便的skeletonView。为了在提取数据时通知片段,我使用了一个侦听器。但是,当我在片段中重写此侦听器接口的方法时,出于某种原因,我会为我的recyclerView获取“kotlin.UninitializedPropertyAccessException:lateinit属性rvShops尚未初始化”,即使它们在接口方法触发时已初始化。我的代码片段如下所示:Android 尽管进行了初始化,lateinit属性尚未在片段中初始化,android,kotlin,google-cloud-firestore,Android,Kotlin,Google Cloud Firestore,格雷廷斯, 我有一个FirestoreRecyclerAdapter,可以从Firestore中提取数据。在提取数据之前,我想显示一个工作方便的skeletonView。为了在提取数据时通知片段,我使用了一个侦听器。但是,当我在片段中重写此侦听器接口的方法时,出于某种原因,我会为我的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()
}
}
类ShopsFragment:Fragment(),ShopsLoadedListener{
伴星{
fun newInstance():ShopsFragment{
退货店碎片()
}
}
私有lateinit var colRefShops:CollectionReference
私有lateinit var shopAdapter:shopAdapter
私有lateinit var v:视图
私有lateinit变量b:FragmentShopsBinding
私有lateinit变量骨架:骨架
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
争论?让我们{
}
(活动作为主活动)。tabLayoutShops.visibility=View.GONE
colRefShops=FirebaseFirestore.getInstance().collection(DB\U商店)
}
覆盖创建视图(充气机:布局充气机,容器:ViewGroup?,savedInstanceState:Bundle?):视图{
v=充气机。充气(右布局图。碎片_车间,容器,假)
返回v
}
覆盖已创建的视图(视图:视图,保存状态:捆绑?){
super.onViewCreated(视图,savedInstanceState)
initRecyclerView()
}
覆盖有趣的onStart(){
super.onStart()
shopAdapter.startListening()
}
私人娱乐initRecyclerView(){
rvShops?.layoutManager=GridLayoutManager(v.context,2)
骷髅=骷髅花
骨架=rvShops.applySkeleton(R.layout.item_shop,10)
skeleton.showSkeleton()
val q:Query=colRefShops.orderBy(重量)
val选项:FirestoreRecyclerOptions=
FirestoreRecyclerOptions.Builder()
.setQuery(q,ModelShop::class.java)
.build()
shopAdapter=shopAdapter(选项,shopsLoadedListener=newInstance())
}
覆盖桌面上的乐趣(){
super.onStop()
shopAdapter.stopListening()
}
覆盖在shopsloaded上的乐趣(i:Int){
Log.d(“dataComes”,“Data=$i”)
rvShops.adapter=shopAdapter//这里我得到了kotlin.UninitializedPropertyAccessException:lateinit属性rvShops在启动此方法时尚未初始化
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)
}
}
类ShopAdapter(选项:FirestoreRecyclerOptions,私有变量shopsLoadedListener:shopsLoadedListener)
:FirestoreRecyclerAdapter(选项){
覆盖数据更改(){
super.onDataChanged()
shopsLoadedListener.onShopsLoaded(5)
}
私有变量v:视图?=null
公共界面ShopsLoadedListener{
快乐在shopsloaded(i:Int)
}
类ShopViewHolder(私有值b:ItemShopBinding):RecyclerView.ViewHolder(b.root)
override onCreateViewHolder(父级:ViewGroup,viewType:Int):ShopViewHolder{
val layoutInflater=layoutInflater.from(parent.context)
val v=布局平坦。充气(R.layout.item_shop,父项,false)
val b=物品商店绑定。充气(平放)
日志d(“火灾”、“ifireincreateviewholder”)
退货店主(b)
}
覆盖BindViewHolder(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)
}
}
错误消息告诉您,在为骨架赋值之前,您试图使用骨架。几乎可以肯定的是,onShopsLoaded
在initrecyclererview
初始化它之前就被调用了。您必须编写代码来检测并正确处理此情况。据我所知,您从未将rvShops
分配给任何会使其未初始化的对象。假设它被设置为lateinit
,那么您将获得UninitializedPropertyAccessException
解决方案:
在片段中的onViewCreated(…)
中分配rvShops
,这样就不会再像那样崩溃了
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, this)
在这种情况下,我实现的方法也能正常工作。这就是奇怪的部分。initRecyclerView()在onShopsLoaded()之前调用,我在initRecyclerView()和onShopsLoaded()中的日志都证明了这一点。正如您在这里看到的,我在崩溃之前得到了一个骨架网格布局,网格中每行有两个项目,这意味着rvShops?.layoutManager=GridLayoutManager(v.context,2)执行得很好。但是,当onShopsLoaded()中的代码被触发时,rvShops突然变为null。另外,如果您说skeleton没有正确初始化,为什么skeleton.showSkeleton()也会执行而没有错误?我现在明白您的意思了,我犯了一个错误,发布了一条错误消息,说skeleton不是init.,但是即使我删除了有关skeleton的所有内容,rvShops在被重写的接口方法上也是空的,这正是我想要说明的问题。不过,这基本上是同一个问题。您在分配之前使用过RVS商店。-这是我的onViewCreated(),现在问题仍然存在。我确信在这种情况下初始化已经完成。按照我执行“rvShops?.layoutManager=GridLayoutManager(v.context,2)”时的相同逻辑,我在分配rvShops之前使用它,但是没有抛出错误,代码按预期执行。我觉得问题出在其他地方,它是特定于重写的onShopsLoaded()的范围的。您的代码根本没有实际分配rvShops,至少从您在这里展示的内容来看没有。您对它的意思是什么
shopAdapter = ShopAdapter(options, this)