【问题标题】:ViewModel onCleared() called on screen rotationViewModel onCleared() 在屏幕旋转时调用
【发布时间】:2021-04-04 15:12:53
【问题描述】:

我正在使用 Hilt 将 ViewModel 注入片段中。但是在屏幕旋转时,会调用ViewModel.onCleared()。这是预期的行为吗?我一直认为ViewModel 可以在屏幕旋转中幸存下来。

因此,ViewModel 被重新创建,我通过比较屏幕旋转时的 ViewModel 哈希码验证了这一点。

这是我的片段代码:

@AndroidEntryPoint
class DashboardFragment : BaseFragment() {

    private val dashboardViewModel: DashboardViewModel by viewModels()
    private var _binding: FragmentDashboardBinding? = null
    private val binding get() = _binding!!


    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        _binding = DataBindingUtil.inflate(
                inflater, R.layout.fragment_dashboard, container, false
        )
        binding.viewModel = dashboardViewModel
        binding.lifecycleOwner = viewLifecycleOwner

        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.adapter = adapter
        setObservers()
    }

    override fun onDestroyView() {
        _binding = null
        super.onDestroyView()

    }
}

ViewModel 看起来像这样:

@HiltViewModel
class DashboardViewModel @Inject constructor() : ViewModel() {

    init {
        //Some code
    }

    override fun onCleared() {
        super.onCleared()
        Timber.e("cleared")
    }
}

【问题讨论】:

  • "这是预期的行为吗?" -- 如果没有minimal reproducible example,我们无法告诉您该行为是否符合预期。例如,如果您手动替换片段作为配置更改的一部分,您将获得一个新的视图模型实例与新片段一起使用。
  • @CommonsWare 我已经添加了代码 sn-p。请看一看。我不是手动替换片段。事实上,我还没有写任何东西来处理配置更改。
  • 在 onDestroyView 中注释掉内部绑定引用的无效会发生什么?
  • @BonanzaDriver 仍然是相同的行为。 onCleared() 调用。
  • 您能否附上您的DashboardViewModel 代码?或者至少是带有注释等的类声明。

标签: android viewmodel dagger-hilt


【解决方案1】:

这不是ViewModel 应该发生的事情。正如你所说,由于方向变化,它们的设计目的是为了在娱乐中生存。

这里似乎发生的是,每当屏幕旋转时,您正在重新创建 Fragment,在活动或类似的 onCreate 中。这会导致 ViewModel 被清除并重新实例化。

【讨论】:

  • 哦,好的。我不认为我正在这样做,但我会再次确认。感谢您的建议
  • 如果您没有找到问题,也许您可​​以编辑您的问题以包括您添加片段的位置,然后我再看看!
【解决方案2】:

也许你在运行这个片段时错过了 .addToBackStack。 但最重要的是:确保在旋转屏幕时不会再次重新创建片段,例如,使用

if (savedInstanceState == null) {
...
}

onCreate、onCreateView等内部

【讨论】:

    猜你喜欢
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    相关资源
    最近更新 更多