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()
调用。
这是崩溃发生时可能发生的情况:
- 用户导航到 ProductFragment
loadItems
被调用并且 Firestore 请求被发送
- 在调用 Firestore successListener 之前,用户向后导航删除 ProductFragment。
- 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
.
中更新其数据
我将我的应用程序连接到 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()
调用。
这是崩溃发生时可能发生的情况:
- 用户导航到 ProductFragment
loadItems
被调用并且 Firestore 请求被发送- 在调用 Firestore successListener 之前,用户向后导航删除 ProductFragment。
- 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
.