ViewPager+Fragment避免重复createview

本文探讨了使用ViewPager与Fragment组合时遇到的问题,特别是关于Fragment重复调用createView方法导致的状态不一致。提供了一种解决方案,通过自定义BaseFragment基类来确保Fragment的行为更符合预期。

ViewPager+Fragment避免重复createview


每次使用ViewPager+Fragment来作为app的框架的时候都要格外小心,因为他们的生命周期有点奇怪,并没有Activity那样来得自然。如何奇怪呢,请看下面日志

打开app,一开始为第一个Fragment
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1 setUserVisibleHint.isVisibleToUser=false
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2 setUserVisibleHint.isVisibleToUser=false
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1 setUserVisibleHint.isVisibleToUser=true
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onAttach
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onCreate
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onAttach
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onCreate
02-09 14:02:12.551 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onCreateView
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onActivityCreated
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis W/FragmentManager: moveToState: Fragment state for MainFragment2{5434690 #0 id=0x7f0c0056 android:switcher:2131492950:1} not updated inline; expected state 3 found 2
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onCreateView
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onActivityCreated
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onStart
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onResume
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onStart
02-09 14:02:12.561 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onResume

切换到第二个Fragment
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3 setUserVisibleHint.isVisibleToUser=false
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1 setUserVisibleHint.isVisibleToUser=false
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2 setUserVisibleHint.isVisibleToUser=true
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onAttach
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onCreate
02-09 14:03:21.981 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onCreateView
02-09 14:03:21.991 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onActivityCreated
02-09 14:03:21.991 30159-30159/com.tianjiyun.glycuresis W/FragmentManager: moveToState: Fragment state for MainFragment3{863ec84 #2 id=0x7f0c0056 android:switcher:2131492950:2} not updated inline; expected state 3 found 2
02-09 14:03:21.991 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onStart
02-09 14:03:21.991 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onResume

切换到第三个Fragment
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4 setUserVisibleHint.isVisibleToUser=false
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2 setUserVisibleHint.isVisibleToUser=false
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3 setUserVisibleHint.isVisibleToUser=true
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onAttach
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onCreate
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onPause
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onStop
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onDestroyView
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onCreateView
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onActivityCreated
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis W/FragmentManager: moveToState: Fragment state for MainFragment4{6fa481c #3 id=0x7f0c0056 android:switcher:2131492950:3} not updated inline; expected state 3 found 2
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onStart
02-09 14:04:54.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onResume

切换到第四个Fragment
02-09 14:05:30.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3 setUserVisibleHint.isVisibleToUser=false
02-09 14:05:30.941 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4 setUserVisibleHint.isVisibleToUser=true
02-09 14:05:30.951 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onPause
02-09 14:05:30.951 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onStop
02-09 14:05:30.951 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onDestroyView

最后且回到第一个Fragment
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1 setUserVisibleHint.isVisibleToUser=false
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2 setUserVisibleHint.isVisibleToUser=false
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4 setUserVisibleHint.isVisibleToUser=false
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1 setUserVisibleHint.isVisibleToUser=true
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onCreateView
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onActivityCreated
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onStart
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment1onResume
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onCreateView
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onActivityCreated
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis W/FragmentManager: moveToState: Fragment state for MainFragment2{5434690 #0 id=0x7f0c0056 android:switcher:2131492950:1} not updated inline; expected state 3 found 2
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onStart
02-09 14:06:05.651 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment2onResume
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onPause
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onStop
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment3onDestroyView
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onPause
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onStop
02-09 14:06:06.101 30159-30159/com.tianjiyun.glycuresis V/Kuby_test: MainFragment4onDestroyView

一般createView都是一次就行了,因为有时候请求网络啊,或者一些数据已经改变了,后来再切回来就恢复了初始状态。Android官方为了性能,做了这样的灵活设置,切换到下一个fragment的时候会预加载相邻的Fragment,然后把不相邻的都销毁掉,切回被销毁掉的Fragment的时候又会重新createView一次。这样做可能性能得到提高,可是实际开发中却显得有点不方便,也许是我没有领会到更高级的写法。那么我只想要他们老老实实的像Activity一样怎么办呢?这就是这篇文章的目的

解决办法:
具体情况看我写的这个demo,自定义了一个Fragment的超类BaseFragment,只要继承这个BaseFragment,不要复写生命周期,复写几个方法就可以了。使用情况请看上面的注释。

下载地址:http://download.youkuaiyun.com/detail/u014736095/9750716


很多时候开发者我为了方便使用了show和hind的方法去控制他们,因为这样可以解决viewpager的预加载问题。但是这样没有切换动画,如重Fragment1切换到Fragment4,用show和hind就不会按照1.2.3-->4这样的切换动画,而是1-->4。


A ViewPager is a layout manager that allows the user to swipe left and right to move between pages of data. In the case of a Fragment-based ViewPager, each page is represented by a Fragment. To use a ViewPager with Fragments, you need to do the following: 1. Create a layout file that contains a ViewPager element. 2. Create a Fragment class that will represent a single page in the ViewPager. This class should inflate a layout that contains any UI elements you want to display on the page. 3. Create an adapter class that extends FragmentPagerAdapter or FragmentStatePagerAdapter. This adapter will be responsible for creating and managing the Fragments that are displayed in the ViewPager. 4. Set the adapter on the ViewPager. Here's an example of how to create a Fragment-based ViewPager: 1. Create a layout file that contains a ViewPager element. For example: ``` <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. Create a Fragment class that will represent a single page in the ViewPager. For example: ``` public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_my, container, false); // TODO: Set up UI elements in the layout return view; } } ``` 3. Create an adapter class that extends FragmentPagerAdapter or FragmentStatePagerAdapter. For example: ``` public class MyPagerAdapter extends FragmentPagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // TODO: Return a new instance of MyFragment for the given position return null; } @Override public int getCount() { // TODO: Return the total number of pages return 0; } } ``` 4. Set the adapter on the ViewPager in your Activity or Fragment. For example: ``` ViewPager viewPager = findViewById(R.id.view_pager); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); ``` That's it! You should now have a functioning Fragment-based ViewPager. Of course, you'll need to fill in the TODOs in the code snippets above to actually display content on the pages.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值