ViewPager+Fragment预加载解决方案
来源:互联网 发布:c语言死循环 编辑:程序博客网 时间:2024/05/27 16:43
之前对ViewPager+Fragment的预加载比较恐惧,只要不要求实现那种左右滑动切换Fragment的效果,我宁可选择4个button+fragment来替换。今天正好有时间看了一下预加载,其实也没那么麻烦。对于预加载,ViewPager的setOffscreenPageLimit的注释写的比较好:
/** * Set the number of pages that should be retained to either side of the * current page in the view hierarchy in an idle state. Pages beyond this * limit will be recreated from the adapter when needed. * * <p>This is offered as an optimization. If you know in advance the number * of pages you will need to support or have lazy-loading mechanisms in place * on your pages, tweaking this setting can have benefits in perceived smoothness * of paging animations and interaction. If you have a small number of pages (3-4) * that you can keep active all at once, less time will be spent in layout for * newly created view subtrees as the user pages back and forth.</p> * * <p>You should keep this limit low, especially if your pages have complex layouts. * This setting defaults to 1.</p> * * @param limit How many pages will be kept offscreen in an idle state. */ public void setOffscreenPageLimit(int limit) { if (limit < DEFAULT_OFFSCREEN_PAGES) { Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + DEFAULT_OFFSCREEN_PAGES); limit = DEFAULT_OFFSCREEN_PAGES; } if (limit != mOffscreenPageLimit) { mOffscreenPageLimit = limit; populate(); } }
利用预加载,你可以同时使几个页面(3-4)保持活跃,当来回切换页面的时候,你将会消耗更少的时间在布局的创建上,这样切换页面会显得更流畅。但是预加载的页面数要尽可能低,因为当页面布局复杂的话,过多的缓存页面会消耗大量的内存。limit默认值为1,意味着会默认预加载当前页面之前和之后的一个页面,那我们将limit值设置为0不就不预加载了呢,经测试还是会加载的。VIewPager既然提供了这么好的机制,为啥不用呢。这边先写一个demo测试下预加载的机制,用Tablayout+ViewPager+Fragment实现页面和tab的切换效果,代码如下:
布局文件:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tabLayout"></android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/viewPager"> </android.support.v4.view.ViewPager></LinearLayout>
BaseFragment:主要用于所有Fragment生命周期的打印,注释掉的部分提供了懒加载的解决方案。
public class BaseFragment extends Fragment{ private static final String TAG ="lifecycle" ; // private boolean isCanLoadData; @Override public void onCreate(@Nullable Bundle savedInstanceState) { Log.e(TAG,getClass().getName()+"--->"+"onCreate"); super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Log.e(TAG,getClass().getName()+"--->"+"onCreateView"); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Log.e(TAG,getClass().getName()+"--->"+"onViewCreated"); // isCanLoadData=true; } @Override public void onResume() { Log.e(TAG,getClass().getName()+"--->"+"onResume"); super.onResume();// if(getUserVisibleHint()){// requestData();// } } @Override public void onDestroyView() { Log.e(TAG,getClass().getName()+"--->"+"onDestroyView"); super.onDestroyView(); // isCanLoadData=false; } @Override public void onPause() { Log.e(TAG,getClass().getName()+"--->"+"onPause"); super.onPause(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { Log.e(TAG,getClass().getName()+" UserVisible--->"+isVisibleToUser); super.setUserVisibleHint(isVisibleToUser);// if(isCanLoadData&&isVisibleToUser){// requestData();// } }// abstract void requestData(); @Override public void onDestroy() { Log.e(TAG,getClass().getName()+"--->"+"onDestroy"); super.onDestroy(); }}
TabViewPageActivity:4个Fragment代码比较简单就不贴出:
public class TabViewPageActivity extends AppCompatActivity { private ViewPager viewPager; private TabLayout tablayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tab_view_page); initView(); initViewPager(); } private void initView() { viewPager=(ViewPager) findViewById(R.id.viewPager); tablayout=(TabLayout)findViewById(R.id.tabLayout); } static class CustomViewPagerAdapter extends FragmentPagerAdapter{ private List<Fragment> fragments=new ArrayList<>(); private List<String> titles; public CustomViewPagerAdapter(FragmentManager fm) { super(fm); initTitle(); } public void addFragment(Fragment fragment){ fragments.add(fragment); } @Override public Fragment getItem(int position) { return fragments.get(position); } private void initTitle() { titles=new ArrayList<>(); titles.add("First"); titles.add("Second"); titles.add("Third"); titles.add("Four"); } @Override public int getCount() { return fragments.size(); } @Override public CharSequence getPageTitle(int position) { return titles.get(position); } } private void initViewPager(){ CustomViewPagerAdapter customViewPagerAdapter=new CustomViewPagerAdapter(getSupportFragmentManager()); customViewPagerAdapter.addFragment(new FirstFragment()); customViewPagerAdapter.addFragment(new SecondFragment()); customViewPagerAdapter.addFragment(new ThirdFragment()); customViewPagerAdapter.addFragment(new FourFragment()); viewPager.setAdapter(customViewPagerAdapter); tablayout.setTabMode(TabLayout.MODE_FIXED); tablayout.setupWithViewPager(viewPager); }}
运行效果图如下:
当第一个页面第一次加载时的Log日志:此时创建了FirstFragment和SecondFragment,并且FirstFragment处于用户可见。
12-21 15:00:45.518 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment UserVisible--->false12-21 15:00:45.518 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment UserVisible--->false12-21 15:00:45.518 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment UserVisible--->true12-21 15:00:45.520 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onCreate12-21 15:00:45.520 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment--->onCreate12-21 15:00:45.522 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onCreateView12-21 15:00:45.523 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onViewCreated12-21 15:00:45.523 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onResume12-21 15:00:45.523 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment--->onCreateView12-21 15:00:45.524 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment--->onViewCreated12-21 15:00:45.524 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment--->onResume
从第一个页面切换到第二个页面时的Log日志:此时创建了ThirdFragment,并且SecondFragment处于用户可见。
12-21 15:07:53.354 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment UserVisible--->false12-21 15:07:53.355 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment UserVisible--->false12-21 15:07:53.355 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment UserVisible--->true12-21 15:07:53.355 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment--->onCreate12-21 15:07:53.356 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment--->onCreateView12-21 15:07:53.359 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment--->onViewCreated12-21 15:07:53.359 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment--->onResume从第二个页面切换到第三个页面时的Log日志:此时创建了FourFragment,因为只缓存当前界面的之前和之后的页面,此时会销毁FristFragment,并且ThirdFragment处于用户可见。
12-21 15:11:31.050 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FourFragment UserVisible--->false12-21 15:11:31.050 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.SecondFragment UserVisible--->false12-21 15:11:31.050 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.ThirdFragment UserVisible--->true12-21 15:11:31.050 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FourFragment--->onCreate12-21 15:11:31.051 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onPause12-21 15:11:31.059 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FirstFragment--->onDestroyView12-21 15:11:31.060 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FourFragment--->onCreateView12-21 15:11:31.062 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FourFragment--->onViewCreated12-21 15:11:31.062 2085-2085/com.ormsqlite E/lifecycle: com.ormsqlite.fragment.FourFragment--->onResume从Log中理清了预加载的过程,一个页面加载的时候它总会预加载之前和之后的页面,其他和它无关的页面会被销毁(注意此时调用onDestroyVIew而不会调用onDestroy)。对于当页面从锁屏到解锁以及退到后台再回到前台的时候只会调用onpause,onresume的情况,我想页面在onresume里加载数据。对于预加载的情况,例如从第一个页面到第二个页面,此时在setUserVisibleHint里加载数据。因为setUserVisibleHint可能先于onViewCreate之前调用,此时如果加载数据,因为页面没有初始化,会报空指针异常,所以加了一个isCanLoadData标志。具体代码如BaseFragment注释掉代码所示。此时可以将BaseFragment设置成一个抽象类,让其他Framgent实现requestData()这个抽象方法就可以。
阅读全文
0 0
- ViewPager+Fragment预加载解决方案
- viewpager fragment 预加载
- viewPager+fragment阻止预加载
- ViewPager + Fragment 预加载问题
- ViewPager+Fragment 预加载问题
- Fragment+Viewpager防止预加载
- ViewPager+Fragment取消预加载
- viewpager+fragment 重写viewpager取消预加载
- Fragment+ViewPager 不预加载下一个Fragment
- fragment 懒加载 viewpager 取消预加载
- ViewPager+Fragment取消预加载(延迟加载)
- Fragment+Viewpager 取消懒加载/预加载
- ViewPager 加载Fragment oncreatview() 方法重复调用最简单解决方案
- Fragment延迟加载技术(解决Viewpager预加载fragment)
- ViewPager+Fragment不预加载页面
- android viewpager+fragment 避免预加载,缓存
- ViewPager+Fragment的预加载问题
- 取消ViewPager中fragment的预加载
- Gradle学习(三)——Gradle Wrapper
- gouwuche加载view
- cts : CtsTelephonyTestCase android.telephony.cts.MmsTest#testSendMmsMessage failed
- 第十三周 【项目1
- [分享]钛极OS(TiJOS)之设备总线支持
- ViewPager+Fragment预加载解决方案
- Intent传值
- 一些基础的MySQL数据库操作语句
- log4j使用过程详解(怎么使用log4j 2)
- Linux进程间通信 —— 信号(下)
- Groovy语言学习:groovy语言简介及基本语法
- 美国2012年总统候选人政治献金数据分析
- JSON(高程笔记)
- PowerDesigner最基础的使用方法入门学习