FragmentContainerView、ViewPager、ViewPager2与 BottomNaviagtionView结合运用的差异
现在市道的运用界面大多是经过一个Fragment容器+底部导航栏结构来完成页面切换的,而当咱们想要去建立一个这样的结构时,上层的Fragment容器是可选的,常见的有FragmentContanerView、ViewPager、ViewPager2。咱们应该怎么挑选呢?这时就需要考虑这三者的本身自带的一些特性差异:
在我现在写的项目中这三者都有运用到,一开端并没有觉得有什么差异,由于写的都是一些很简单的项目。但在一次运用FragmentContainerView的进程中,我显着的感觉到了其与ViewPager2的一个明显差异:切换Fragment时生命周期办法的调用。
在这个运用FragmentContainerView+BottomNavigationView的项目中,我在其中一个页面加入了自定义的主动轮播图控件,而当我经过底部导航栏切换到另一界面再切回来时,我发现我的轮播图控件总是会主动从第一张图开端加载,而在我之前运用ViewPager2+BottomNaviagtionView的项目中我也运用了主动轮播图控件,可是并没有呈现这个问题:即经过底部导航栏切换到另一个页面再切回来并不会使轮播图控件从头轮播。
我开端考虑:是什么导致了主动轮播图控件每次切回来都会从头开端轮播?
以下是我的排查进程:
一开端,我置疑我的轮播图主动轮播的逻辑写的有问题,回来检查,发现与另一个项目的是相同的,那就能够扫除这个原因
然后,我开端考虑轮播图的加载机遇。我的轮播图数据是网络数据,而恳求轮播图网络数据是在Fragment的onViewCreated()生命周期办法中履行的。也便是说与Fragment的生命周期办法调用机遇有关。
1.FragmentContainerView+BottomNavigationView切换Fragment时的生命周期调用状况:
我开端在Fragment的各个生命周期办法中打Log,然后发现,当我经过底部导航栏切换FragmentContainerView中的fragment时,被切换的Fragment除了主页的Fragment只会当即履行onPause()->onStop()->onDestroyView(),其他的都会当即履行onPause()->onStop()->onDestroyView(onDestory(),当我再切换回来之后,会履行onCreatedView()->onViewCreated()。也便是说每逢我切换回去之后轮播图都会再从头恳求一次数据,然后导致了每次切换回轮播图界面轮播图都会从头开端轮播。
主页Fragment被切换后的生命周期调用状况
从头切回主页Fragment后的生命周期调用状况
其他Fragment被切换后的生命周期调用状况
从头切回其他Fragment后的生命周期调用状况
2.ViewPager2+BottomNavigationView切换Fragment的生命周期调用状况:
然后,我又回来去检查另一个项目(即运用ViewPager2+BottomNavigationView的)的界面切换导致的Fragment生命周期办法的改变。发现:当经过BottomNavigationView切换fragment时,被切换的fragment只会履行onPause(),但并不会当即履行onStop(),而是等候一段时间后或当用户退出运用才会调用onStop()办法;且当切回去时,也不会从头履行onCreatedView()->onViewCreated(),onCreatedView()->onViewCreated()只要当Fragment初度被展现时才会调用。故运用ViewPager2的项目中切换Fragment不会导致轮播图数据从头加载而导致轮播图从头轮播。
Fragment被切换后生命周期调用状况
Fragment被切回来后生命周期调用状况
3.ViewPager+BottomNaviagtionView切换Fragment的生命周期调用状况:
然后,我又研讨了一下ViewPager+BottomNaviagtionView切换fragment的生命周期调用状况。ViewPager有预加载功用,比较复杂一点
相同是只要三个页面(Title,Leaderboard,Register),由BottomNavigationView操控切换:
初度加载时,ViewPager会预加载其接近的一个Fragment,在这个比如中,便是显现主页Title页面时也预加载了Leaderboard页面,生命周期调用如下:
当我从Title切换到接近的Leaderboard页面时,被切换的Title页面的生命周期没有任何改变,切换后的Leaderboard页面也没有任何改变(由于其现已被预加载过了),而此刻,与Leaderboard接近的Register页面也会被预加载,生命周期调用如下:
而当我从Leaderboard页面切换到第三个页面Register时,Leaderboard页面和Register页面的生命周期都不会发生改变,但第一个页面Title会被毁掉,生命周期调用如下:
相同的,当我从第三个页面Register切换到第二个页面Leaderboard时,第一个页面Title又会被从头加载,生命周期调用如下:
当我再从第二个页面Leaderboard切换到第一个界面时,第三个页面Register又会被毁掉,生命周期办法调用如下:
由上述测验咱们能够看到ViewPager的预加载机制和页面毁掉机制,且当界面上只要三个页面时,除非用户退出界面,不然第二个页面是永久不会毁掉的。
4.总结:
(1)FragmentContainerView+BottomNavigationView:
既没有预加载机制也没有缓存机制,每切换一次,被切换的Fragment就会被毁掉,下次切回来要从头创立View:onCreatedView()->onViewCreated()
(2)ViewPager2+BottomNavigationView:
默许是没有预加载机制的,除非咱们手动调用viewPager.offscreenPageLimit 特点进行设置,不然默许是没有预加载(其预加载与ViewPager的预加载机制还不太相同,预加载的界面不会调用onResume()烘托界面,而ViewPager的预加载界面是直接烘托好的),可是默许有缓存机制,当页面被加载到界面上后不会毁掉(除非用户退出界面),只会暂停onPause,再次回来时直接onResume()
(3)ViewPager+BottomNavigationView:
默许有预加载机制,会预加载接近的左右页面。也有默许的缓存机制,但与ViewPager2的不同,当从本页面切换到距离一个的页面,本页面就会被毁掉(如从1切换到3时,1就会被毁掉)。