当前位置: 首页 > 知识库问答 >
问题:

底部导航组合之间的延迟/慢速导航-Jetpack Compose

彭霄
2023-03-14

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

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

问题是这会导致它们之间的导航速度太慢。每次导航时,线圈图像的加载时间约为400ms至700ms。YouTube/LinkedIn等应用程序在其底部导航栏中几乎是即时的。

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

我如何用Compose达到同样的效果?

我使用以下版本:

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

共有1个答案

董飞
2023-03-14

嗯,我在使用模拟器或电话时遇到了同样的问题,这两种方法都能很好地处理小型的、简单的组件。当我创建更复杂的组合并尝试使用伴奏动画库为导航设置动画时,它变得非常滞后。但后来我尝试构建发布版APK文件,因为它通常经过优化,速度更快,这将显著加快你的应用程序。这里有一个链接,介绍如何生成签名的APK,然后将其安装到手机或模拟器上,看看这是否能解决您的问题!

您还可以检查是否意外地从清单中禁用了硬件加速。确保您在活动标签中设置了< code > Android:hardware accelerated = " true "

如果这也没有帮助,那么您必须实现您自己的动画并使用共享视图模型,用于通信和触发从一个可组合组件到另一个组件的转换。这个想法是,您可以使用modifier offset属性,通过将可组合组件放置在屏幕之外来显示/隐藏它。

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

这不是最佳实践,因为无法像通常使用普通导航时那样直接将数据从一个可组合文件传递到另一个文件。但您仍然可以使用共享视图模型共享数据。使用此方法将不会重新组合可组合文件,因此速度非常快。到目前为止,我没有任何内存不足的问题,即使是在一些非常旧/速度很慢的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)
            }
        }
    }
}

这是使用可组合导航和伴奏动画的结果。正如你所看到的,它确实非常滞后

现在这里是使用我们的自定义动画的结果,它非常平滑,因为没有可组合的被重新组合。

 类似资料:
  • 我有一个关于底部导航栏的奇怪问题,虽然我花了大量时间在它上面,但我无法解决。当我以“推荐”的方式(从许多教程中)使用它时,它就是无法导航。 那么,我所说的“推荐”方式是什么意思呢:我有一个单独的acticity,其中有一个名为“MainActivity”的navHostFragment。这个主要活动有一个XML布局文件,我将底部导航栏放在其中。BottomNavigationBar还有一个XML布

  • 实现tabbar建议采用小程序原生的tabbar,通过设置page/main.js(即对应小程序中app.json)来实现,详情请看小程序文档。示例如下,仅作参考: tabBar: { color: '#999999', selectedColor: '#1AAD16', backgroundColor: '#ffffff', borderStyle: 'white', /*

  • BottomBar有4个目的地:ScreenA,ScreenB,ScreenC和ScreenD。 在ScreenA上按下按钮(不是底部栏项)时,我想使用参数转到ScreenB。 导航图 底部栏 到目前为止,单击ScreenA上的按钮会将我导航到ScreenB,但参数值始终为0,因为我永远不会传递在lambda中传递的参数。我使用的是compose_version='1.2.0-alpha04'和"

  • 我正在将我的应用程序更新为导航架构组件,我发现它在替换导航抽屉中可见的片段时存在延迟,无法顺利关闭。 直到现在,我一直在遵循这种方法: https://vikrammnit.wordpress.com/2016/03/28/facing-navigation-drawer-item-onclick-lag/ 所以我在中导航而不是在中导航以避免故障。 这是一个非常常见的问题,但它又回来了。使用导航组

  • Tabbar 底部导航栏 1.4.8 优点: 此组件一般用于应用的底部导航,具有如下特点: 可以设置凸起的按钮,且是全端通用的 图标可以使用字体图标(内置图标和扩展图标)或者图片 可以动态切换菜单的数量以及配置 切换菜单之前,可以进行回调鉴权 可以设置角标 有效防止组件区域高度塌陷,无需给父元素额外的内边距或者外边距来避开导航的区域 缺点: 虽然优点很多,但是如果用此组件模拟tabbar页面的话依

  • 我有一个导航抽屉的问题,它太慢了,我正在寻找的解决方案是关闭抽屉,然后显示活动,但它不工作,当然我错过了一些东西。