【问题标题】:Problems with fragment instantiation on ui threadui线程上的片段实例化问题
【发布时间】:2020-12-29 10:14:51
【问题描述】:

这是一个比较笼统的问题,因为我不确定我是否遗漏了什么。

我的设置如下:单一活动应用程序,使用导航组件并使用Stepper Layout by Stepstone 启动片段。

这个步进器包含四个片段,其中一个在 ui 线程上非常重。稍微想象一下,它有 2 个地图视图、大量编辑文本和其他基于位置的内容。

当我启动这个步进器片段时,我得到了明显的延迟,android 停止导航动画并在完成后立即打开步进器。在我看来,这是一个非常糟糕的迹象,因为在速度较慢的设备上启动它时可能会有明显的延迟。

我现在的假设是,这是因为一个沉重的片段而发生的(如果我用其他片段填充步进器,则没有滞后)。我尝试将 onViewCreated 中该片段的所有初始逻辑包装到 viewLifecycleOwner.lifecycleScope.launch{...} 函数中,但无济于事。

总结一下:

很遗憾,我无法指出导致这种延迟的单点代码,但是在实例化片段时有什么方法可以减少 ui 线程负载,或者是它的错完全是 UI 线程?

我现在唯一的想法是完全替换这个步进器并基于导航组件构建我自己的,但这只是最后尝试的解决方案,因为它需要最大的努力。

【问题讨论】:

  • 究竟什么是“基于位置的东西”。你应该把所有繁重的工作从主线程上移开。也许您可以通过仅膨胀您的视图而不进行任何其他繁重的计算来追踪问题,反之亦然。所以你会知道滞后来自哪里。
  • @ChristianB 正在初始化一个融合的位置提供程序,但理论上只有当该片段中的一个按钮被按下时,所以我怀疑是什么导致了主线程上的繁重负载。我认为很可能是两个地图视图和导致问题的文本观察器
  • 如果您以编程方式创建视图并且需要一段时间,您也可以考虑在主线程之外执行此操作。完成后,您可以将结果返回到主线程以将其显示在您的片段中。
  • 你不能在工作线程中移动所有繁重的负载吗?
  • @Christianb 有没有推荐的方法来使用 kotlin 协程来做到这一点?

标签: android android-fragments fragment kotlin-coroutines android-jetpack


【解决方案1】:

如果您以编程方式创建视图并且需要一段时间(因为您需要创建很多视图),您可以考虑在主线程之外执行此操作。完成后,您可以将结果返回到主线程并将其添加到片段中的视图层次结构中。

您可以在onCreateView() 中进行基本的视图初始化。

override fun onCreateView(): View? {
  // create your basic view first
}

然后在onViewCreated() 中,您可以开始计算繁重的视图部分(使用协程或任何其他线程机制),例如:

override fun onViewCreated(...) {
  lifecycleScope.launch(Dispatchers.Main) { 
    val complexView: View = heavyViewCreation() // result comes back on the main thread (Dispatchers.Main)
    // add complexView to your existing view hierachy
  }
}

suspend fun heavyViewCreation(): View = withContext(Dispatchers.Default) {
  // create your complex view here, computation is off the main thread (Dispatchers.Default)
}

文档

【讨论】:

  • 感谢您的回答,因为它回答了我最初的问题。但是我刚刚意识到我的滞后是由初始片段视图实例化造成的,特别是在这个片段中的一个额外的地图视图组合,如果单击一个按钮,它将被覆盖。我将进一步调查为什么这个地图片段会如此多地挂起片段初始化,如果我能找到问题,我会提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多