我正在参与「·启航计划」
前语
首先要做相关优化,就得先要大致明晰影响功能的相关要素,这样可以做针对性调优会比较有条理。
比较常见的功能调优要素有:
- 内存:Java 一般通过 JVM 对内存进行分配办理,主要是用 JVM 中堆内存来存储 Java 创建的对象。体系堆内存的读写速度十分快,所以根本不存在读写功能瓶颈。但由于内存成本要比磁盘高,相比磁盘,内存的存储空间又十分有限。所以当内存空间被占满,对象无法收回时,就会导致内存溢出、内存走漏等问题。
- 反常:抛出反常需要构建反常栈,对反常进行捕获和处理,这个过程十分耗费体系功能。
- 网络:关于传输数据比较大,或许是并发量比较大的体系,网络就很简单成为功能瓶颈。
- CPU: 杂乱的计算,会长时刻,频频地占用cpu履行资源;例如:代码递归调用,JVM频频GC以及多线程情况下切换资源都会导致CPU资源繁忙。
对以上这些要素可以在代码中做相关优化处理。
推迟加载(懒加载)优化
了解预加载
- ViewPager控件有预加载机制,即默认情况下当时页面左右相邻页面会被加载,以便用户滑动切换到相邻界面时,更加顺利的显示出来
- 通过ViewPager的setOffscreenPageLimit(int limit)可设置预加载页面数量
介绍推迟加载
等页面UI展示给用户时,再加载该页面数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载部分,甚至更多页面数据。可提高所属Activity的初始化速度,另一方面也可以为用户节省流量.而这种推迟加载方案现已被诸多APP所选用。
相关归纳
- 没有打开页面,就不预加载数据,当页面可见时,才加载所需数据。
- 换句话说推迟加载便是可见时才去恳求数据。
- 实际应用开发中有哪些推迟加载案例:
- ViewPager+Fragment 搭配运用推迟加载
- H5网页运用推迟加载
ViewPager与Fragment推迟加载的场景
- ViewPager中setOffscreenPageLimit(int limit)部分源码
//默认的缓存页面数量(常量)
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
//缓存页面数量(变量)
private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES;
public void setOffscreenPageLimit(int limit) {
//当我们手动设置的limit数小于默认值1时,limit值会自动被赋值为默认值1(即DEFAULT_OFFSCREEN_PAGES)
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) {
//通过前面的阻拦判断后,将limit的值设置给mOffscreenPageLimit,用于
mOffscreenPageLimit = limit;
populate();
}
}
- 思路分析:Fragment中setUserVisibleHint(),此办法会在onCreateView()之前履行,当viewPager中fragment改动可见状况时也会调用,当fragment 从可见到不见,或许从不可见切换到可见,都会调用此办法,运用getUserVisibleHint() 可回来fragment是否可见状况。在onActivityCreated()及setUserVisibleHint()办法中都调一次lazyLoad() 办法。
public abstract class BaseMVPLazyFragment<T extends IBasePresenter> extends BaseMVPFragment<T> {
/**
* Fragment的View加载结束的符号
*/
protected boolean isViewInitiated;
/**
* Fragment对用户可见的符号
*/
protected boolean isVisibleToUser;
/**
* 是否懒加载
*/
protected boolean isDataInitiated;
...
/**
* 榜首步,改动isViewInitiated符号
* 当onViewCreated()办法履行时,标明View现已加载结束,此时改动isViewInitiated符号为true,并调用lazyLoad()办法
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitiated = true;
//只有Fragment onCreateView好了,
//别的这里调用一次lazyLoad()
prepareFetchData();
//lazyLoad();
}
/**
* 第二步
* 此办法会在onCreateView()之前履行
* 当viewPager中fragment改动可见状况时也会调用
* 当fragment 从可见到不见,或许从不可见切换到可见,都会调用此办法
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
prepareFetchData();
}
/**
* 第四步:界说抽象办法fetchData(),具体加载数据的作业,交给子类去完成
*/
public abstract void fetchData();
/**
* 第三步:在lazyLoad()办法中进行两层符号判断,通往后即可进行数据加载
* 榜首种办法
* 调用懒加载,getUserVisibleHint()会回来是否可见状况
* 这是fragment实现懒加载的关键,只有fragment 可见才会调用onLazyLoad() 加载数据
*/
private void lazyLoad() {
if (getUserVisibleHint() && isViewInitiated && !isDataInitiated) {
fetchData();
isDataInitiated = true;
}
}
/**
* 第二种办法
* 调用懒加载
*/
public void prepareFetchData() {
prepareFetchData(false);
}
/**
* 第三步:在lazyLoad()办法中进行两层符号判断,通往后即可进行数据加载
*/
public void prepareFetchData(boolean forceUpdate) {
if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
fetchData();
isDataInitiated = true;
}
}
}
多线程优化: 建议运用线程池
用线程池的好处
可重用线程池中的线程,避免频频地创建和毁掉线程带来的功能耗费;有用控制线程的最大并发数量,防止线程过大导致抢占资源造成堵塞;可对线程进行有用办理
- RxJava,RxAndroid,底层对线程池的封装办理十分值得参阅。