Android,无法从分离的片段访问 ViewModel
Android, Can't access ViewModels from detached fragment
每次我旋转 phone 时,它都会崩溃并在 SearchResultFragment 中打印奇怪的异常 不管 isDetached
value is false:
java.lang.IllegalStateException: Can't access ViewModels from detached fragment
在这部分代码中:
private val searchViewModel: SearchViewModel by viewModel()
fun searchWord(word: String) {
if(!isDetached) searchResultViewModel.searchWord(word)
}
从另一个片段 SearchFragment 调用:
searchResultFragment.searchWord(searchWord)
SearchResultFragment是这样添加到SearchFragment中的:
private val searchResultFragment = SearchResultFragment()
private fun addFragment() {
val fragmentTransaction = childFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.searchContainer, searchResultFragment)
fragmentTransaction.commit()
}
我正在使用 Koin 进行依赖注入。我将不胜感激所有提示。
如果没有完整的上下文,很难准确了解发生了什么。
我看到的第一个问题(也被其他一些用户提到)是您似乎在从另一个片段调用片段中的 public 方法。这是一个危险信号,因为您现在将两个生命周期独立的对象相互耦合(除其他外)。
如果有的话,快速摆脱这种情况的方法是您可以改为依赖 共享视图模型,它与两个 Fragment 对话并可以提供您想要的状态。
无论如何,由于很难说清到底发生了什么,您可以在 onCreateView(...)
...
中尝试类似的操作
if (savedInstanceState == null) {
supportFragmentManager.commit {
replace(
R.id.searchContainer,
SearchResultFragment.newInstance(),
SearchResultFragment::class.java.simpleName
)
}
}
newInstance()
在 SearchResultFragment 中实现为:
companion object {
fun newInstance() = SearchResultFragment()
}
接下来,由于我们不知道完整的情况,您可以改为尝试查看 Fragment Manager 是否已经有您的片段...
类似这样的东西(伪代码...)
if (savedInstanceState == null) {
val newFragment = supportFragmentManager.findFragmentByTag(SearchResultFragment::class.java.simpleName) ?: SearchResultFragment.newInstance()
supportFragmentManager.commit {
replace(
R.id.simple_fragment_container,
newFragment,
SearchResultFragment::class.java.simpleName
)
}
}
这样,您添加带有标记的片段(只是一个字符串来标识它们),然后您检查片段管理器是否已经拥有它并使用它,而不是总是创建一个新实例。
最后但同样重要的是,这可能会受到许多其他(外部)因素的影响:
Fragment/Appcompat/AndroidX/etc 的版本。您正在使用(您可能知道,Fragment Manager 不是 Android 中最好的 class... 一直在进行许多修复和更改)。
Android 版本:一些 Android API 比其他 API 的“碎片运气”更好(尤其是在我们拥有单独的工件来更改“碎片”版本之前) .
我认为 Koin 对此没有任何补充,但请确保您至少使用最新的稳定版。
也许你能做的最好的事情就是依赖 ViewModel 而不是所有这些 if (!detached) {...}
东西。你真的在与框架作斗争并沿着 FragmentManager 摆脱,有时甚至 Google 都不敢做...
每次我旋转 phone 时,它都会崩溃并在 SearchResultFragment 中打印奇怪的异常 不管 isDetached
value is false:
java.lang.IllegalStateException: Can't access ViewModels from detached fragment
在这部分代码中:
private val searchViewModel: SearchViewModel by viewModel()
fun searchWord(word: String) {
if(!isDetached) searchResultViewModel.searchWord(word)
}
从另一个片段 SearchFragment 调用:
searchResultFragment.searchWord(searchWord)
SearchResultFragment是这样添加到SearchFragment中的:
private val searchResultFragment = SearchResultFragment()
private fun addFragment() {
val fragmentTransaction = childFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.searchContainer, searchResultFragment)
fragmentTransaction.commit()
}
我正在使用 Koin 进行依赖注入。我将不胜感激所有提示。
如果没有完整的上下文,很难准确了解发生了什么。
我看到的第一个问题(也被其他一些用户提到)是您似乎在从另一个片段调用片段中的 public 方法。这是一个危险信号,因为您现在将两个生命周期独立的对象相互耦合(除其他外)。
如果有的话,快速摆脱这种情况的方法是您可以改为依赖 共享视图模型,它与两个 Fragment 对话并可以提供您想要的状态。
无论如何,由于很难说清到底发生了什么,您可以在 onCreateView(...)
...
if (savedInstanceState == null) {
supportFragmentManager.commit {
replace(
R.id.searchContainer,
SearchResultFragment.newInstance(),
SearchResultFragment::class.java.simpleName
)
}
}
newInstance()
在 SearchResultFragment 中实现为:
companion object {
fun newInstance() = SearchResultFragment()
}
接下来,由于我们不知道完整的情况,您可以改为尝试查看 Fragment Manager 是否已经有您的片段...
类似这样的东西(伪代码...)
if (savedInstanceState == null) {
val newFragment = supportFragmentManager.findFragmentByTag(SearchResultFragment::class.java.simpleName) ?: SearchResultFragment.newInstance()
supportFragmentManager.commit {
replace(
R.id.simple_fragment_container,
newFragment,
SearchResultFragment::class.java.simpleName
)
}
}
这样,您添加带有标记的片段(只是一个字符串来标识它们),然后您检查片段管理器是否已经拥有它并使用它,而不是总是创建一个新实例。
最后但同样重要的是,这可能会受到许多其他(外部)因素的影响:
Fragment/Appcompat/AndroidX/etc 的版本。您正在使用(您可能知道,Fragment Manager 不是 Android 中最好的 class... 一直在进行许多修复和更改)。
Android 版本:一些 Android API 比其他 API 的“碎片运气”更好(尤其是在我们拥有单独的工件来更改“碎片”版本之前) .
我认为 Koin 对此没有任何补充,但请确保您至少使用最新的稳定版。
也许你能做的最好的事情就是依赖 ViewModel 而不是所有这些
if (!detached) {...}
东西。你真的在与框架作斗争并沿着 FragmentManager 摆脱,有时甚至 Google 都不敢做...