讨论了两年的 Navigation 保存 Fragment 状态问题居然被关闭了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lear7
V2EX    Android

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

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

    讨论地址

    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     Solana     3385 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 04:42 PVG 12:42 LAX 20:42 JFK 23:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86