Kotlin 片段未附加到上下文

Kotlin Fragment not attached to a context

我将我的应用程序连接到 Crashlytic,但出现此错误:

Fatal Exception: java.lang.IllegalStateException: Fragment ProductFragment not attached to a context.
   at androidx.fragment.app.Fragment.requireContext(Fragment.java:900)
   at androidx.fragment.app.Fragment.getResources(Fragment.java:964)
   at com.example.fragments.ProductFragment$loaditems.onSuccess(ProductFragment.kt:60)
   at com.example.fragments.ProductFragment$loaditems.onSuccess(ProductFragment.kt:21)
   at com.google.android.gms.tasks.zzn.run(:4)
   at android.os.Handler.handleCallback(Handler.java:873)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:214)
   at android.app.ActivityThread.main(ActivityThread.java:6981)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

我从未见过我的应用程序崩溃,这很奇怪。因此我不知道什么样的事情会触发错误。

这是我的代码:

package com.example.fragments

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.adapters.MyProductAdapter
import com.example.R
import com.example.models.productmodel
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import org.json.JSONArray
import java.io.IOException
import java.io.InputStream

class ProductFragment : Fragment() {

   private var recyclerView: RecyclerView? = null
   private var errorscreen: LinearLayout? = null
   private var loadingscreen: LinearLayout? = null
   private var gridLayoutManager: GridLayoutManager? = null
   private var arrayList: ArrayList<productmodel> ? = null
   private var adapter: MyProductAdapter? = null
   private val tabel = "producten_nl"

   override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
   ): View? {
      val v = inflater.inflate(R.layout.fragment_producten, container, false)

      loadingscreen = v.findViewById(R.id.productloadingscreen)
      recyclerView = v.findViewById(R.id.json_listp)
      errorscreen = v.findViewById(R.id.errorscreen)

      gridLayoutManager = GridLayoutManager(getActivity(), 2, LinearLayoutManager.VERTICAL, false)
      recyclerView?.layoutManager = gridLayoutManager
      recyclerView?.setHasFixedSize(true)
      arrayList = ArrayList()
      arrayList = loaditems()

      return v
   }

   private fun loaditems(): ArrayList<productmodel> {
      val items: ArrayList<productmodel> = ArrayList()
      val db = Firebase.firestore

      db.collection(tabel)
         .orderBy("volgorde")
         .get()
         .addOnSuccessListener { result ->
            if (result.count() != 0) {
               for (document in result) {
                  if(document.getBoolean("show") == true) {
                     val photo = resources.getIdentifier(document.getString("image"), "drawable", requireContext().packageName)
                     val name = document.getString("name") as String
                     val image = document.getString("image") as String
                     val url = document.getString("url") as String

                     items.add(productmodel(photo, name, image, url))
                  }
               }
               adapter = MyProductAdapter(requireActivity().baseContext, arrayList!!)
               recyclerView?.adapter = adapter
               recyclerView?.visibility = View.VISIBLE
               loadingscreen?.visibility = View.GONE
            }
            else
            {
               errorscreen?.visibility = View.VISIBLE
               recyclerView?.visibility = View.GONE
               loadingscreen?.visibility = View.GONE
            }
         }
         .addOnFailureListener { exception ->
            errorscreen?.visibility = View.VISIBLE
            recyclerView?.visibility = View.GONE
            loadingscreen?.visibility = View.GONE
         }
      return items
   }
}

第 60 行是这一行:if(document.getBoolean("show") == true) { 第 21 行是这一行:class ProductFragment : Fragment() {

我不知道这个错误是什么以及导致这个错误的原因。有谁知道我做错了什么?

编辑: 这就是我将 fragman 放入 activity

的方式
    private fun  makeCurrentFragment(fragment: Fragment) =
    supportFragmentManager.beginTransaction().apply {
        replace(R.id.fl_wrapper, fragment)
        commit()
    }

罪魁祸首是您的 Firestore 请求 successListener 中的 requireContext() 调用。

这是崩溃发生时可能发生的情况:

  1. 用户导航到 ProductFragment
  2. loadItems 被调用并且 Firestore 请求被发送
  3. 在调用 Firestore successListener 之前,用户向后导航删除 ProductFragment。
  4. Firestore 请求完成并调用 successListener,但现在片段不再附加到任何上下文,因此 requireContext() 抛出 IllegalStateException

一个快速解决方法是在继续之前检查 successListener 中的上下文是否为空,return 如果是:

.addOnSuccessListener { result ->
   val context = context ?: return
   if (result.count() != 0) {
      for (document in result) {
         if(document.getBoolean("show") == true) {
            val photo = resources.getIdentifier(document.getString("image"), "drawable", context.packageName)
            val name = document.getString("name") as String
            val image = document.getString("image") as String
            val url = document.getString("url") as String

            items.add(productmodel(photo, name, image, url))
         }
      }
      ...

您还调用了 successListener 中的 requireActivity(),在相同情况下同样会失败。与其在 successListener 中初始化适配器,不如在发出请求之前对其进行初始化,然后仅在 successListener.

中更新其数据