【问题标题】:Laggy/Slow Navigation between BottomNavigation composables - Jetpack ComposeBottomNavigation 组合组件之间的延迟/慢速导航 - Jetpack Compose
【发布时间】:2021-11-02 06:18:38
【问题描述】:

我正在使用带有 4 个可组合项的 BottomNavigation。它们都有一个LazyColumnLazyColumn 中的每个项目都有一个使用Coil for Jetpack Compose 从网络填充的图像。类似于 Twitter/YouTube。

当我在这些项目之间导航时,可组合项会被破坏并仅在导航回它们时才重新组合。在这些可组合项之间导航时,甚至线圈图像也会被清除并重新获取(从内存或本地存储中)。这当然是预期的行为。

问题是这会导致它们之间的导航太慢。线圈图像需要大约 400 毫秒到 700 毫秒来加载每次导航的图像。 YouTube/LinkedIn 等应用在其BottomBar 导航中几乎是即时的。

当我为此使用 XML 时,我会使用出现/消失逻辑制作片段(用作底部导航项)以避免在它们之间导航时出现这种时间延迟。

如何使用 Compose 实现相同的目标?

我正在使用以下版本:

//compose navigation
implementation "androidx.navigation:navigation-compose:2.4.0-beta01"
implementation "com.google.accompanist:accompanist-navigation-animation:0.21.0-beta"

【问题讨论】:

    标签: android android-jetpack-compose android-jetpack android-jetpack-navigation


    【解决方案1】:

    嗯,我在使用 emulator or phone 时遇到了同样的问题,两者都适用于小型简单的可组合项。当我创建更复杂的 Composable 并尝试为导航设置动画时,使用伴奏动画库会变得非常滞后。 但后来我尝试构建发布 APK 文件,因为它通常经过优化并且速度更快,这将显着加快您的应用程序的速度。 Here is link on how you can generate signed APK 然后安装到你的手机或者模拟器上看看能不能解决你的问题!

    您还可以检查是否不小心从清单中禁用了硬件加速。确保在活动标签中设置android:hardwareAccelerated="true"

    如果这也无济于事,那么您必须实现自己的动画并使用 Shared ViewModel 进行通信并触发从一个 Composable 到另一个的转换。这个想法是您可以使用修饰符 offset 属性来显示/隐藏 Composable,方法是将其放置在屏幕外。

    首先设置您的 ViewModel,并添加可变状态变量,这将触发从 Home 到 Settings 的转换,反之亦然。

    这不是最佳实践,因为无法像正常导航那样直接将数据从一个可组合对象传递到另一个对象。但是您仍然可以使用 Shared ViewModel 共享数据。使用这种方法,它不会重新组合您的 Composable,因此速度非常快。到目前为止,即使在一些具有 2GB RAM 的非常老/慢的设备上,我也没有任何内存不足异常的问题。

    class SharedViewModel : ViewModel() {
    
        // changing this mutable state will trigger the transition animation
        private val _switchHomeToSetting = mutableStateOf(true)
        val switchHomeToSetting: State<Boolean> = _switchHomeToSetting
    
        fun switchHomeToSettings() {
            _switchHomeToSetting.value = !_switchHomeToSetting.value
        }
    }
    

    现在分别创建您的两个可组合函数 Home 和 Settings

    @Composable
    fun HomeScreen(viewModel: SharedViewModel) {
       // draw your subcomponents
    }
    
    @Composable
    fun SettingsScreen(viewModel: SharedViewModel) {
       // draw your subcomponents
    }
    

    最后在你的主要活动中初始化动画

    class MainActivity : ComponentActivity() {
       
        val viewModel by viewModels<CityWeatherViewModel>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
     
            setContent { 
                
                // set your offset animation
                val density = LocalDensity.current
                val width = with(density) { (1.adw).toPx() }
                val animatedOffsetX: Float by animateFloatAsState(
                    targetValue = if (!viewModel.switchHomeToSetting.value) 0f else width,
                    animationSpec = tween(1200)
                )
    
                // Home screen
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .offset { IntOffset((-width + animatedOffsetX).toInt(), 0) }
                ) {
                    HomeScreen(viewModel = viewModel)
                }
    
                // Settings screen
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .offset { IntOffset(animatedOffsetX.toInt(), 0) }
                ) {
                    SettingsScreen(viewModel = viewModel)
                }
            }
        }
    }
    

    这是使用Composable NavigationAccompanist Animation 的结果。如您所见,它确实非常滞后

    现在这是使用我们自定义动画的结果,它非常流畅,因为没有重新组合 Composable。

    【讨论】:

      猜你喜欢
      • 2022-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多