V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lear7
V2EX  ›  Android

讨论了两年的 Navigation 保存 Fragment 状态问题居然被关闭了

  •  
  •   lear7 · 2021-03-12 15:45:30 +08:00 · 11026 次点击
    这是一个创建于 1352 天前的主题,其中的信息可能已经有所发展或是发生改变。

    讨论地址

    https://github.com/android/architecture-components-samples/issues/530

    问题描述

    大概两年前开始使用 Navigation,当时觉得把所有 Fragment 都保存在一个导航图的理念很先进,然后就用了,然后发现每次 Fragment 都会重新创建,如果从 A 页面到 B 页面,然后返回 A 页面,那么 A 页面会被重建,FragmentA - FragmentB - New FragmentA,无论用户还是开发者都是不希望页面被重建的,https://github.com/android/architecture-components-samples/issues/530#issuecomment-658360926

    Workaround

    于是有了这位同学的解决方法,https://github.com/android/architecture-components-samples/issues/530#issuecomment-526455102

    public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
                @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
            
    //      ft.replace(mContainerId, frag);
    
    //      change to  
    
            if(mFragmentManager.getFragments().size()>0){
                ft.hide(mFragmentManager.getFragments().get(mFragmentManager.getFragments().size()-1));
                ft.add(mContainerId, frag);
            }else {
                ft.replace(mContainerId, frag);
            }
            
    }
    

    于是就这样用了一年多,但是这个方法用起来也确实会有很多内存消耗问题,而且在非主流配置的机器上,页面跳转明显比官方的 Navigate()方法响应慢。

    问题照旧

    于是又翻了下这个问题的讨论情况,发现还是老样子,官方坚持说这么做会消耗大量内存,https://github.com/android/architecture-components-samples/issues/530#issuecomment-789131002 说这里是给你讨论我的 sample 代码的 issue 的,不是讨论 library 本身的??还坚持说我 Fragment 也没问题(没有任何人报告 issue ),各种保存和恢复机制都给你做好了等等等等,然后把问题关了??

    请问下有用使用 Navigation 的同学吗?请说说你们的看法,谢谢!

    15 条回复    2022-05-15 01:03:48 +08:00
    Lin0936
        1
    Lin0936  
       2021-03-12 16:00:13 +08:00
    在用 navigation,用 viewmodel 保存状态,UI 重建无所谓
    fragment 本身就挺垃圾😂
    james2013
        2
    james2013  
       2021-03-12 18:15:38 +08:00
    使用 Navigation 后,发现 A 界面是复杂的 fragment,返回到 A 界面重建时间耗费太长。而且 A 界面的 ViewModel 的数据又会重新更新一遍...
    直接放弃使用了.
    shily
        3
    shily  
       2021-03-12 18:50:13 +08:00
    直接弃用了,改回跳转 Activity 了。每次跳转回来时界面闪一下,不能接受。
    yumerdev93
        4
    yumerdev93  
       2021-03-13 08:07:31 +08:00
    上面 show hide 的解决方法用了一年了,基本没问题。viewmodel 保存状态是个不错的方案,但是我不太喜欢😂
    ikas
        5
    ikas  
       2021-03-13 21:07:19 +08:00
    用 show,hide 也有很多问题,1.view 的层级问题,先 show 的 view 在下面,当你在次需要显示时,实际他是在新页面的下面,尤其做 xy 轴动画,可以明显看到.2.生命周期问题,hide 的视图,本身生命周期并没有任何改变,所以需要你配置最大生命周期,当设置为 STARTED 时会导致动画执行是在 RESUMED 之后.导致刷新数据造成动画卡顿,还会会导致 viewmodel 的监听不正常,如果设置为 CREATED,又会导致 view 重建..然后其他小问题就不说了..反正坑.官方说内存问题,就很搞笑啊,当内存不够时再销毁 fragment 不行么..就连 uwp 的 page 都支持 NavigationCacheMode(Disabled, Enabled, Required);目前我是自己实现了这样的东西,但是已经不想用了
    slyang5
        6
    slyang5  
       2021-03-13 21:50:52 +08:00
    fragment 这个组件 简直就是 垃圾中的垃圾 ,30%的 crash 和它有关
    cgpiao
        7
    cgpiao  
       2021-03-14 00:34:03 +08:00 via iPhone
    字节不是创建了导航库吗,可以用那个。叫 scene, 官方 navigation 我觉得是半成品,包括 fragment 。
    sankemao
        8
    sankemao  
       2021-03-14 11:32:07 +08:00 via iPhone
    google 的 api 向来很难用,比如 paging3
    lear7
        9
    lear7  
    OP
       2021-03-15 09:10:59 +08:00
    @ikas 我没怎么用到动画,当普通使用都会发现这个问题,所以页面统统不能设置透明的,不然会上一个页面会透出来。而且右上角的 optionmenu 也需要每个页面重新清空和增加,不然也会显示错乱。
    lear7
        10
    lear7  
    OP
       2021-03-15 09:11:17 +08:00
    @cgpiao 好的,感谢分享,我去了解一下!
    zhanlanhuizhang
        11
    zhanlanhuizhang  
       2021-03-15 20:23:14 +08:00
    我也有这个问题。但是仔细研究后,可以重写 FragmentNavigator 下的 navigate 方法,然后重写 NavHostFragment 下的 onCreateNavController 方法。就可以自己想怎么控制,就怎么控制,虽然还是坑。
    zhanlanhuizhang
        12
    zhanlanhuizhang  
       2021-03-15 20:25:14 +08:00
    我这里是配合 BottomNavigationView 一起用,所以网上的方法不管用,最后需要自己研究。
    ikas
        13
    ikas  
       2021-03-15 23:23:31 +08:00
    @zhanlanhuizhang 是重写,但是他这个问题不仅仅是 FragmentNavigator 问题,还有 Fragment 等的问题,目前基本都是重写,用 show,hide,但是 show,hide 根本不足以满足,还需要配合生命周期.....反正解决一个问题又来一个问题,然后发现越来越复杂了
    ikas
        14
    ikas  
       2021-03-15 23:25:52 +08:00
    @lear7 只用 show,hide,应该是没法解决这个问题了.目前想参考 viewpager2 来实现,但是本质 Fragment 的复杂,还是可预见的一堆问题
    lisongeee
        15
    lisongeee  
       2022-05-15 01:03:48 +08:00
    最近在用 Android Compose 的 navigation ,也是会出现这种情况,从页面 A 跳转到页面 B ,然后调用 navController.popBackStack 返回,页面 A 的所有状态都重置了,这个 compose 的开发理念和前端 react 的 hooks 基本一致,但是在 kotlin 语法糖的加持下,个人感觉开发效率比 react hooks 高,但是 react-router 也是和 compsoe 一样,路由 /栈 回退就会重新重建,除了路由参数还在,你啥都不能保存,除非你把这个页面所有的状态保存在上一个层级。但是 vue-router 就有 keep-alive ,可以缓存之前的状态,md ,这咋就这么难用呢,就不能延续之前的多 activity 模式吗,新建一个栈的时候,直接覆盖渲染,底下的栈直接停止更新渲染不行?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2866 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 14:13 · PVG 22:13 · LAX 06:13 · JFK 09:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.