问题是这样的,项目中有 用到tablayout+viewpager+fragment这个顶部导航模块,切换的tab大概有十个,除了第一tab的fragment,其他tab的fragment都是同一个class只是数据不同。因为是电商的app,所以图片特别多等等原因的占用内存比较大,再加上这块fragment对象多因此这块的优化需求就有了。
ps:公司项目原因,不便传截图。
项目中最初是这样的,废话不多说直接上代码
@Override
public FragmentgetItem(intposition) {
if(position ==0) {
return newHomeFragment();
}else{
returnOtherCategoryFragment.newInstance();
}
}
public static OtherCategoryFragment newInstance(intid,String categoryName) {
OtherCategoryFragment otherCategoryFragment =newOtherCategoryFragment();
otherCategoryFragment.categoryId= id;
otherCategoryFragment.categoryName= categoryName;
returnotherCategoryFragment;
}
viewpageradapter中getitem中每次都是调用fragment的newInstance方法,然而newInstance方法都是直接new一个对象。我的天啊,这能忍,岂不是每次切换都会new对象的。于是我开始了第一次优化:
@Override
public Fragment getItem(int position) {
Fragment fragment;if(fragments.size() <= position) {
if(position ==0) {
fragment = PrimeHomeFragment.newInstance();
}else{
fragment = PrimeOtherCategoryFragment.newInstance(categories.get(position).id, position); }
fragments.add(fragment); }else{
fragment = fragments.get(position);
}
returnfragment;
}
其实我就是加了个ArrayList fragments来保存new出来的fragment,当第二次使用该fragment时候直接取出来不再是油重新new一个对象。眼尖的人或许看出来了这种做法too young,因为viewpager会自己管理fragments,默认缓存(预加载)DEFAULT_OFFSCREEN_PAGES =1参赛,其他页面fragment会自动finish掉,所以我用list保存fragment并没什么卵用的,超出缓存数还是会继续new。于是开启了继续优化
viewPager.setOffscreenPageLimit(fragmentList.size()-1);
上面提到过viewpager会自动管理缓存的,默认为DEFAULT_OFFSCREEN_PAGES=1。那我设置全部缓存不就ok了么,嗯,问题是解决了,然而产品会杀了你,因为加载第一个页面时候把把所有页面预加载出来才会完整显示第一个页面,所以第一个页面会等很久很久。于是开始了继续优化
@Override
public Fragment getItem(int position) {
Fragment fragment;
if(fragments.size() <= position) {
if(position ==0) {
fragment = PrimeHomeFragment.newInstance();
}else{
fragment = PrimeOtherCategoryFragment.newInstance(categories.get(position).id, position); }
fragments.add(fragment); }else{ //returnPrimeOtherCategoryFragment.newInstance(categories.get(position).id); fragment = fragments.get(position);
//returnfragments.get(position); }
//保存Fragment
Bundle bundle = new Bundle();
bundle.putString("id",""+ position);
fragment.setArguments(bundle);returnfragment;
}@Override
public Fragment instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position); fm.beginTransaction().show(fragment).commit();
returnfragment; }
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// super.destroyItem(container, position, object); fm.beginTransaction().hide(fragments.get(position)).commit();
}
这种优化的基本思路是底部导航栏的思路,采用hide和show来控制。也就是第一次加载出来后,再到该fragment就通过调用show方法来显示。当然确定也就是super.destroyItem没被调用,也就是fragment对象会一直存在那,内存占用问题没很好的解决,于是再再下次优化开始
思路:其实针对我们项目本身tab切换的fragment虽然十来个很多,可除了第一个其他的是同一个fragment只是数据不同而已。于是listview的优化思路出来了,即共用ui,切换界面其实只是刷数据而已,具体我还没去实现只有这个思路,大概列出几个注意的点:
自己管理viewpager对fragment的new和destory管理
自行设计fragmnet与pageradapter间的通信
ps:有更好思路的,可以说说意见一起试试。。还有简书不能Markdown么 ?
网友评论