您的位置:首页 > 娱乐 > 八卦 > 怎么做企业网站优化_目前最好的旅游网站_十大中文网站排名_数据分析

怎么做企业网站优化_目前最好的旅游网站_十大中文网站排名_数据分析

2025/3/12 9:43:32 来源:https://blog.csdn.net/qq_40853919/article/details/146169271  浏览:    关键词:怎么做企业网站优化_目前最好的旅游网站_十大中文网站排名_数据分析
怎么做企业网站优化_目前最好的旅游网站_十大中文网站排名_数据分析

目录:

  1. 前言
  2. 定义导航图(Navigation Graph)和路由(Route),用代码声明页面跳转逻辑
    2.1 composeable页面卸载的时候,数据如何保存?
    2.2 composeable挂载页面的时候,是覆盖,还是替换呢?

一、前言

最近在学习compose,先是找文章来学习,然后看github上面的源码来学习,最后再找视频来学习,然后再上github的项目学习,接着在根据项目的源码,自己删除再重新写一遍。一波三折。

在学习的过程,我就有一个疑问,只有一个Activity,也没有看到Fragment呢,也没有看到更多的Fragment,我好奇,compose的生命周期是如何的,他的页面又是如何加载的,没看到onstart方法,或者页面停止的时候onstop方法。

接下来,我们来解答一下这些疑惑。


二、通过定义导航图(Navigation Graph)和路由(Route),用代码声明页面跳转逻辑

在 Jetpack Compose 中,不再推荐使用多个 Activity 或 Fragment 来实现页面跳转,而是采用 单一 Activity + 多 Composable 组件 + 导航库 的架构。这是 Compose 的核心理念:通过声明式 UI 和状态驱动的导航来简化开发。

  1. 单一 Activity:整个应用通常只有一个 Activity(MainActivity),所有页面切换通过 Composable 组件 的替换完成。
  2. 无 Fragment:Compose 完全抛弃 Fragment,直接通过 NavController 和 NavHost 管理页面栈。
  3. 声明式导航:通过定义导航图(Navigation Graph)和路由(Route),用代码声明页面跳转逻辑。

那么,为什么要使用这种方式呢?

  1. 传统多 Activity/Fragment 的痛点:
    1.1 每个 Activity 都有自己的生命周期,跨页面数据传递需要序列化(Parcelable/Serializable),容易导致内存泄漏或状态不一致
    1.2 每次跳转新 Activity 都会触发冷启动,导致界面卡顿。
  2. Compose 新架构的核心优势
    2.1 Composable 函数根据状态自动重组,无需手动更新视图。页面切换本质是 Composable 组件的重组,无需启动新 Activity 或 Fragment。
    2.2 通过 NavController 管理全局导航栈,跳转逻辑集中且类型安全。

接下来,我们就看看导航是如何使用的(需要有一定基础~~)。


2.1 代码例子

1、导航代码

fun AppScaffold() {val navCtrl = rememberNavController() // 获取导航控制器val navBackStackEntry by navCtrl.currentBackStackEntryAsState() // 监听导航栈变化 从而确定当前选中的底部导航项。这样可以确保底部导航栏的状态与当前显示的路由一致。val currentDestination = navBackStackEntry?.destination // 当前路由目标//接下来我要构建底部一个导航栏,所以需要使用到ScaffoldScaffold(modifier = Modifier.statusBarsPadding().navigationBarsPadding(),//底部的导航栏内容,会放到NavHost里面。bottomBar = {when (currentDestination?.route) {RouteName.HOME-> {BottomNavBarView(navCtrl = navCtrl)}RouteName.CATEGORY-> {BottomNavBarView(navCtrl = navCtrl)}RouteName.COLLECTION-> {BottomNavBarView(navCtrl = navCtrl)}RouteName.PROFILE-> {BottomNavBarView(navCtrl = navCtrl)}}},content = {// 定义需要保持状态的页面索引(防止页面切换时重置)var homeIndex = remember { 0 }var categoryIndex = remember { 0 }// 导航宿主容器NavHost(modifier = Modifier.background(MaterialTheme.colors.background),navController = navCtrl,startDestination = RouteName.HOME // 初始路由) {// 首页路由composable(route = RouteName.HOME) {HomePage(navCtrl)}// 分类页路由composable(route = RouteName.CATEGORY) {CategoryPage(navCtrl)}// 收藏页路由composable(route = RouteName.COLLECTION) {CollectPage(navCtrl)}// 个人中心页路由composable(route = RouteName.PROFILE) {ProfilePage(navCtrl)}}})
}

2、点击切换

@Composable
fun BottomNavBarView(navCtrl: NavHostController) {//导航的标题,图片,路径val bottomNavList = listOf(BottomNavRoute.Home,BottomNavRoute.Category,BottomNavRoute.Collection,BottomNavRoute.Profile)//底部导航栏ui。BottomNavigation {val navBackStackEntry by navCtrl.currentBackStackEntryAsState() // 监听导航栈变化 从而确定当前选中的底部导航项。这样可以确保底部导航栏的状态与当前显示的路由一致。val currentDestination = navBackStackEntry?.destination// 当前路由目标bottomNavList.forEach { screen ->BottomNavigationItem(modifier = Modifier.background(AppTheme.colors.themeUi),icon = {Icon(imageVector = screen.icon,contentDescription = null)},label = { Text(text = stringResource(screen.stringId)) },//判断当前页面是否在某个导航图中selected = currentDestination?.hierarchy?.any { it.route == screen.routeName } == true,//那个被选择,那个就高亮。onClick = {//如果点击相同的,那么就不管if (currentDestination?.route == screen.routeName) {return@BottomNavigationItem}//跳转navCtrl.navigate(screen.routeName)})}}
}

3、HomePage :一个背景,其他页面也都是,用来测试,就写的简单一些~

@Composable
fun HomePage(navCtrl: NavHostController,
) {Box(modifier =Modifier.fillMaxSize().background(Color.Red))
}

在这里插入图片描述
这里,还有一个疑问,那么他重组,其他页面内容又是如何保存的呢?还是说直接就销毁了呢?比如从首页切换到分类,那么是覆盖,还是什么呢?


2.2 挂载和卸载

Composable 的挂载/卸载:当 Composable 进入/退出组合(Composition)时,可以视为类似 onStart/onStop 的时机。可以通过

1、挂载(进入组合)

当 Composable ​首次被调用 或 ​在重组中被重新需要 时,会挂载到组合中。

初始化状态:通过 remember 或 mutableStateOf 创建的状态会被初始化。
​执行副作用:如 LaunchedEffect、DisposableEffect 的首次运行。
​构建 UI 树:将 Composable 添加到 Compose 的 UI 树中。

示例


@Composable
fun MyComponent() {// 挂载时初始化状态val count = remember { mutableStateOf(0) }// 挂载时启动副作用LaunchedEffect(Unit) {delay(1000)println("Component mounted!")}Text("Count: ${count.value}")
}
2、卸载(退出组合)

当 Composable ​在重组过程中不再被调用 时,会从组合中卸载。

常见场景:

条件语句跳过:因 if/when 条件不满足而不再执行。
​导航离开页面:通过 NavController 跳转到其他页面。
​父组件卸载:父 Composable 被卸载导致子组件连带卸载。

行为:
​清理副作用:触发 DisposableEffect 的 onDispose 或取消 LaunchedEffect 的协程。
​释放资源:如取消网络请求、关闭数据库连接。
​从 UI 树移除:Composable 的 UI 节点被销毁。

示例


@Composable
fun ParentComponent(showChild: Boolean) {if (showChild) {ChildComponent() // 挂载}// 当 showChild 变为 false 时,ChildComponent 卸载,因为条件不满足了,这里要好好理解。因为ChildComponent方法不被调用了,就会卸载掉。
}@Composable
fun ChildComponent() {// 副作用:挂载时启动,卸载时清理DisposableEffect(Unit) {val resource = allocateResource()onDispose {releaseResource(resource) // 卸载时执行清理}}Text("Child Component")
}

现在我们可以回答一个问题,比如从首页切换到分类,那么是覆盖,还是什么呢?不是覆盖,是重新绘制,消失就会被卸载掉,不会留着,绘制变更的内容。

那么页面数据呢?也会初始化,重新获取数据?看你使用的是什么样的

一、Composable 卸载后的状态

  1. ​状态是否销毁?

    ​普通状态(remember)​:
    使用 remember 保存的状态 ​会被销毁。当 Composable 卸载后,其内部状态会被释放,下次挂载时会重新初始化。

    
    @Composable
    fun Counter() {val count = remember { mutableStateOf(0) } // 卸载时销毁Button(onClick = { count.value++ }) {Text("Count: ${count.value}")}
    }
    

    ​可保存状态(rememberSaveable)​:
    使用 rememberSaveable 的状态会在 ​配置变更(如屏幕旋转)时保留,但 ​Composable 完全卸载后依然会被销毁。

val count = rememberSaveable { mutableStateOf(0) } // 配置变更保留,卸载销毁
  1. ​副作用是否清理?

    LaunchedEffect/DisposableEffect
    卸载时会自动取消协程或触发 onDispose 清理资源。

    DisposableEffect(Unit) {// 挂载时执行onDispose { // 卸载时清理 }}
    

二、重新挂载时的行为

当 Composable ​再次被调用进入组合 时(例如条件语句重新满足、导航返回页面等),会触发 ​重新挂载,此时:

  1. ​重新执行整个函数体

Composable 函数会从头到尾重新执行,包括:

所有 remember 的初始化
所有副作用的启动(如 LaunchedEffect)
  1. ​状态重置

除非使用 ​状态提升 或 ​持久化存储,否则状态会被重置:

// 示例:重新挂载时状态重置
@Composable
fun DynamicComponent(visible: Boolean) {if (visible) {val count = remember { mutableStateOf(0) } // 每次挂载都从 0 开始Button(onClick = { count.value++ }) {Text("Count: ${count.value}")}}
}

那么怎么办呢?使用viewmodel,大家应该都知道viewmodel的生命周期。其生命周期与 Activity/Fragment 或导航图绑定。通过 ViewModel 保存状态。


@Composable
fun PersistentCounter(viewModel: CounterViewModel = viewModel()) {Button(onClick = { viewModel.increment() }) {Text("Count: ${viewModel.count.value}")}
}class CounterViewModel : ViewModel() {val count = mutableStateOf(0)fun increment() { count.value++ }
}

比如说,我们发起一起请求,请求到的数据放到viewModel中,那么重新挂载的时候,直接把数据拿出来就可以,不需要重新执行请求

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com