Android,无法从分离的片段访问视图模型



每次旋转手机时,无论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
)
}
}

通过这种方式,您可以添加带有标记的片段(只是一个字符串来标识它们(,然后检查片段管理器是否已经拥有它并使用它,而不是总是创建一个新实例。

最后但同样重要的是,这可能受到许多其他(外部(因素的影响:

  1. Fragment/Appcompat/AndroidX/等的版本。你正在使用(正如你可能知道的,Fragment Manager不是安卓系统中最好的类……总是会发生很多修复和更改(。

  2. Android版本:一些Android API有更好的";碎片运气";(尤其是在我们有单独的工件来更改"片段"版本之前(。

  3. 我不认为Koin对此有任何补充,但请确保您至少使用了最新的稳定版本。

  4. 也许你能做的最好的事情就是依赖ViewModel,而不是所有这些if (!detached) {...}。你真的在与框架作斗争,摆脱FragmentManager,这有时甚至谷歌都不敢做。。。

最新更新