性能优化系列之fragment的懒加载
来源:互联网 发布:各个国家顶级域名 编辑:程序博客网 时间:2024/05/18 01:54
自从实习以来一直在忙着赶项目进度,没有时间(懒)总结。现在终于有空总结一下这两个多月的收获了。从性能优化中的fragment懒加载开始梳理吧。
项目中使用ViewPager+Fragment,拿练手项目xMusic来说吧,在MainActivity中有两个fragment,一个是本地播放页面,一个是“发现”页面,“发现”页面包含广告轮播图和推荐歌单,图片资源比较多。正常打开app时两个fragment都会进行网络请求加载资源。刚打开app的时候,内存占用能上到88-90m。对于很大一部分只听本地歌曲的用户来说,加载“发现”页面不仅占用内存,还消耗网络资源。
ViewPager中有一个方法 setOffscreenPageLimit(int limit) 可以设置预加载的页面数量。通过源码我们可以知道,这个方法设置的limit最终都不会小于1。因此对于我们这种情况,setOffscreenPageLimit(int limit)是无效的。
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();
}
}
这时候就需要使用fragment的懒加载机制,在用户手动滑入“发现”页面时fragment才进行加载,节省资源。
fragment中提供一个方法 setUserVisibleHint,这个方法会在fragment对用户可见/不可见时回调,但是它并不在fragment的生命周期中,因此无法保证和生命周期方法的调用顺序。
创建一个抽象类BaseLazyFragment,然后定义几个标识位
private boolean isFirstVisible = true;
private boolean isFirstInvisible = true;
private boolean isViewCreated;
private boolean isUIVisible;
重写方法onViewCreated,并在其中进行加载操作(最终是否加载还取决于当前fragment是否可见,这将在lazyLoad中进行判断):
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
isViewCreated = true;
lazyLoad(); // 执行懒加载,因为无法确定setUserVisibleHint和onViewCreated哪个方法先执行,因此两个方法里面都需要调用lazyLoad
}
然后重写方法:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isUIVisible = true; //当前fragment可见
if (isFirstVisible) {
//如果是第一次可见,则进行懒加载
isFirstVisible = false;
lazyLoad();
} else {
//不是第一次可见,则调用onUserVisible()
onUserVisible();
}
} else {
isUIVisible = false;
if (isFirstInvisible) {
isFirstInvisible = false;
//第一次不可见
onFirstUserInvisible();
} else {
//非第一次不可见
onUserInvisible();
}
}
}
添加lazyLoad方法,执行懒加载:
private void lazyLoad() {
if (isViewCreated && isUIVisible) { //需要进行双重判断,避免因为setUserVisibleHint先于onViewCreaetd调用时,出现空指针
onFirstUserVisible(); //进行初次可见时的加载
}
}
添加几个抽象方法:
protected abstract void onFirstUserVisible();
protected abstract void onUserVisible();
protected abstract void onFirstUserInvisible();
protected abstract void onUserInvisible();
Fragment的懒加载大概就是这样,比较简单。添加几个标识位判断是否是第一次可见/不可见、onViewCreated是否执行完(必要,否则setUserVisibleHint在onViewCreated执行完前回调,然后进行懒加载的话可能会导致空指针)。在加入懒加载之后,打开app时的内存占用能降到70m左右,下降了近20%,对于一些性能较差的用户还是比较关键的。
不过懒加载也有坏处就是用户第一次进入页面时需要短暂等待加载。因此是否需要懒加载得根据产品定位、目标人群等来决定,这就是产品经理需要考虑的问题了蛤蛤。
完整的BaseLazyFragment代码如下:
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public abstract class BaseLazyFragment extends Fragment {
private boolean isFirstVisible = true;
private boolean isFirstInvisible = true;
private boolean isViewCreated;
private boolean isUIVisible;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("LazyLoad", getClass().getName() + "onCreateView");
if (getLayoutId() != 0) {
return inflater.inflate(getLayoutId(), container, false);
} else {
return super.onCreateView(inflater, container, savedInstanceState);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
isViewCreated = true;
lazyLoad(); // 执行懒加载,因为无法确定setUserVisibleHint和onViewCreated哪个方法先执行,因此两个方法里面都需要调用lazyLoad
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isUIVisible = true; //当前fragment可见
if (isFirstVisible) {
//如果是第一次可见,则进行懒加载
isFirstVisible = false;
lazyLoad();
} else {
//不是第一次可见,则调用onUserVisible()
onUserVisible();
}
} else {
isUIVisible = false;
if (isFirstInvisible) {
isFirstInvisible = false;
//第一次不可见
onFirstUserInvisible();
} else {
//非第一次不可见
onUserInvisible();
}
}
}
private void lazyLoad() {
if (isViewCreated && isUIVisible) { //需要进行双重判断,避免因为setUserVisibleHint先于onViewCreaetd调用时,出现空指针
initViewsAndEvents();
onFirstUserVisible(); //进行初次可见时的加载
}
}
protected abstract int getLayoutId();
protected abstract void initViewsAndEvents();
protected abstract void onFirstUserVisible();
protected abstract void onUserVisible();
protected abstract void onFirstUserInvisible();
protected abstract void onUserInvisible();
}
阅读全文
0 0
- 性能优化系列之fragment的懒加载
- Android优化方案之--Fragment的懒加载实现
- [Android 性能优化系列]布局篇之动态加载布局
- [Android 性能优化系列]布局篇之动态加载布局
- iOS 性能优化之懒加载
- 多个Fragment时的加载优化,使用懒加载
- Android性能优化之:加载Bitmap优化
- APP性能优化之图片加载优化
- Android Viewpager+Fragment的懒加载优化问题
- Android系列之Fragment----Fragment加载到Activity (转载)
- Trinea性能优化系列之数据库优化
- Android性能优化系列之布局优化
- Android性能优化系列之布局优化
- Android性能优化系列之渲染优化
- Android性能优化系列之电量优化
- listview加载性能优化之view的复用
- ListView加载性能优化之ViewHolder的作用与用法
- 页面加载的性能优化
- 中科院分词系统(NLPIR)JAVA简易教程(转载)
- Android多线程机制
- win7_不主动发送智能卡命令
- js计算出现多位小数-Javascript 浮点运算问题分析与解决
- Runtime浅析
- 性能优化系列之fragment的懒加载
- HDU 6201 树形DP 或 最长路
- Linux基础命令
- GoF:(Gang of Four,GOF设计模式)---四人组
- 区块链架构与应用(区块链入门篇)
- jQuery Mobile学习笔记(一)——移动平台
- JavaScript 常用55个技巧
- Optimizing Rule Placement in Software-Defined Networks for Energy-aware Routing
- (六)redis常用数据类型 SortedSet