ea6387ef0345515755e13bb711bb3543--809802570.jpg
我正在参与「·启航计划」

前语

首先要做相关优化,就得先要大致明晰影响功能的相关要素,这样可以做针对性调优会比较有条理。

比较常见的功能调优要素有:

  • 内存: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,底层对线程池的封装办理十分值得参阅。