Android Fragments AndroidKotlin- requireContext()在Android Fragment的onViewCreated中抛出IllegalStateException

gcxthw6b  于 2023-08-06  发布在  Android
关注(0)|答案(2)|浏览(189)

我正在处理与onViewCreated中使用getString有关的IllegalStateException崩溃;查看堆栈跟踪,这通过getResources返回到requireContext,如果context为null,则抛出IllegalStateException。
我可能可以通过使用getContext()并检查是否为空来解决这个问题,但这让我想知道是否存在某些场景,其中在片段生命周期的onViewCreated步骤中上下文为空。
我的堆栈跟踪也显示了这些崩溃发生在onViewCreated中定义的CoroutineScopes中。
如果有任何关于这个主题的反馈,我将不胜感激,因为通过代码,我正确地调用了getString函数,没有任何奇怪的位置,如在导航之后。下面是堆栈跟踪。我在Android 13设备上运行这个应用程序。- 谢谢-谢谢

Exception java.lang.IllegalStateException:
  at androidx.fragment.app.Fragment.requireContext (Fragment.java)
  at androidx.fragment.app.Fragment.getResources (Fragment.java)
  at androidx.fragment.app.Fragment.getString (Fragment.java:1053)
  at com.example.MyFragment$onViewCreated$1$2.invokeSuspend (MyFragment.kt) //this leads me to think inside Coroutines is where its crashing.
  at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt)
  at kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt)
  at android.os.Handler.handleCallback (Handler.java:942)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8757)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

字符串

kpbwa7wx

kpbwa7wx1#

堆栈跟踪未指向onViewCreated。注意跟踪中的函数名实际上是onViewCreated$1$2。这是为您在onViewCreated中启动的协程创建的虚函数名。所以崩溃发生在onViewCreated之后的某个时间,大概是在onDetach之后,所以在那个时候上下文是空的。
这是一种反模式,创建一个CoroutineScope并立即从它启动一个协程,而不首先将CoroutineScope存储在一个属性中,这样当它使用的东西超出范围时,您就可以取消它。您正在创建一个全局协同程序,并且可能也使用GlobalScope。CoroutineScope().launch是一种代码气味,因为它是一个全局协程,而不是在GlobalScope中启动的,这表明作者不确定他们在做什么。
偶尔会用到全局协程,但在绝大多数情况下,您不希望您的协程是全局的。协程通常处理的东西超过几毫秒,所以如果它正在做的工作变得过时,你想取消它,以避免浪费资源和内存超过必要的时间。更重要的是,也有像您这样的情况,您试图获取不再可用的Context,因此触发了崩溃。
Android Fragments已经提供了viewLifecycleOwner.lifecycleScope,您可以从中启动协程。当Fragment视图被销毁时,它会自动取消所有它已经启动的协程,这可以保护您在不必要的时间内保留过时的视图引用,或者在上下文不再可用时尝试获取上下文。
使用Dispatchers.IO启动协程也应该是罕见的,特别是在Android上,其中有太多的类要求它们只在主线程上被触及。Dispatchers.Main应该是您的默认值,它已经是lifecycleScope的默认值。Dispatchers.IO用于调用 * 阻塞 * 代码。一般来说,您应该只在withContext(Dispatchers.IO) { }中使用它来 Package 协程中的块代码。
还要注意,如果suspend函数遵循约定,它们就不会阻塞。它们在内部使用所需的任何线程/调度器,因此在调用时不需要将它们 Package 在withContext中。

eaf3rand

eaf3rand2#

//检查片段是否附加到有效的上下文

if (getContext() != null) {

字符串
//现在可以安全地访问资源和执行其他操作了

val yourString = getString(R.string.your_string_resource)

    }


或者您也可以查看
requireActivity()。

相关问题