每次旋转手机时,无论isDetached
值为false,它都会崩溃并在SearchResultFragment中打印奇怪的异常:
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进行依赖项注入。我将感谢所有的提示。
如果没有完整的上下文,很难准确地看到发生了什么。
我看到的第一个问题(其他一些用户也提到过(是,您似乎正在从另一个Fragment调用Fragment中的公共方法。这是一个危险信号,因为您现在正在将两个独立于生命周期的对象相互耦合(除其他外(。
如果说有什么不同的话,那就是你可以依赖一个共享视图模型,它可以与两个Fragments对话,并可以提供你想要的状态。
无论如何,由于很难判断到底发生了什么,您可以在onCreateView(...)
中尝试这样的操作。。。
if (savedInstanceState == null) {
supportFragmentManager.commit {
replace(
R.id.searchContainer,
SearchResultFragment.newInstance(),
SearchResultFragment::class.java.simpleName
)
}
}
newInstance()
在SearchResultFragment中实现为:
companion object {
fun newInstance() = SearchResultFragment()
}
接下来,因为我们不知道全貌,你可以试着看看碎片管理器是否已经有了你的碎片。。。
类似这样的东西(伪代码…(
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/等的版本。你正在使用(正如你可能知道的,Fragment Manager不是安卓系统中最好的类……总是会发生很多修复和更改(。
Android版本:一些Android API有更好的";碎片运气";(尤其是在我们有单独的工件来更改"片段"版本之前(。
我不认为Koin对此有任何补充,但请确保您至少使用了最新的稳定版本。
也许你能做的最好的事情就是依赖ViewModel,而不是所有这些
if (!detached) {...}
。你真的在与框架作斗争,摆脱FragmentManager,这有时甚至谷歌都不敢做。。。