美文网首页
Android性能优化-启动优化

Android性能优化-启动优化

作者: 程序狮 | 来源:发表于2023-02-15 10:53 被阅读0次

    一、主页面布局优化

    应用主界面布局优化是老生常谈了,综合起来无非就是下面两点,这个需要结合具体的界面布局去做优化,网上也有比较多的资料可以查阅

    • 通过减少冗余或者嵌套布局来降低视图层次结构
    • 用 ViewStub 替代在启动过程中不需要显示的 UI 控件
      viewstub就是动态加载试图;也就是在我们的app启动绘制页面的时候,他不会绘制到view树中;当在代码中执行inflate操作后,她才会被添加到试图中。其实ViewStub就是一个宽高都为0的一个View,它默认是不可见的,只有通过调用setVisibility函数或者Inflate函数才 会将其要装载的目标布局给加载出来,从而达到延迟加载的效果,这个要被加载的布局通过android:layout属性来设置。最终目的是把app加载页面的速度提高了,使用户体验更好.
    • 使用自定义 View 替代复杂的 View 叠加

    二、闲时调用

    在应用启动的时候,为了加快启动速度,往往需要把一些比较重的操作放到子线程中,或者是延时加载。将任务放在子线程中是一个比较简单并且看起来有效的操作,但是呢,也不能太过于依赖子线程,它虽然不会阻塞主线程,但是却会跟主线程抢占CPU,当子线程很多并且任务很重的时候,也还是会拖慢主线程的,不信你可以打出Systrace看一下。延时加载也是一个比较好的策略,但难点就在于延时多久,这个时间并不好掌控。

    1、延时加载 IdleHandler

        /**
         * Callback interface for discovering when a thread is going to block
         * waiting for more messages.
         */
        public static interface IdleHandler {
            /**
             * Called when the message queue has run out of messages and will now
             * wait for more.  Return true to keep your idle handler active, false
             * to have it removed.  This may be called if there are still messages
             * pending in the queue, but they are all scheduled to be dispatched
             * after the current time.
             */
            boolean queueIdle();
        }
    

    简单来说,就是当MessageQueue中没有更多的消息的时候就会回调queueIdle()这个方法,返回true的话,当MessageQueue中没有消息的时候还会继续回调这个方法,返回false则会在执行完之后移除掉这个监听。
    原理就是这么简单了,接下来就是动手优化代码了,代码也很简单。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
    
     // ...
    
     // 拿到主线程的MessageQueue
     Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
    
     @Override
     public boolean queueIdle() {
      // 在这里去处理你想延时加载的东西
      delayLoad();
    
      // 最后返回false,后续不用再监听了。
      return false;
     }
     });
    }
    

    写起来一点都不难,只是我们需要掌握这么一个知识点而已。这里多说一句,网上很多关于冷启动优化的文章都说到了ViewPager的懒加载,即等到用户滑动过去的时候才去加载界面,我们在项目中最开始也是这样做的,但其实这样的体验真的很不好,所以我们利用IdleHandler做了一个延时加载,即不影响主界面的启动工作,又能在主线程空闲下来的时候立刻去加载出其它的Tab,在性能和体验之间找到一个最好的平衡。

    三、App 瘦身

    App 瘦身包括代码瘦身和资源瘦身,通常的做法如下:

    • Inspect Code :Android Studio 提供的代码审查工具,实际上是内嵌了 Lint
    • 代码混淆
    • 图片格式的选择:如果对图片的要求不高,可以换成 565
    • 接入资源混淆
    • 减少 Dex 数量

    四、线程优化

    线程优化主要是减少 CPU 调度带来的波动,让启动时间更稳定。如果启动过程中有太多的线程一起启动,会给 CPU 带来非常大的压力,尤其是比较低端的机器。过多的线程同时跑会让主线程的 Sleep 和 Runnable 状态变多, 增加了应用的启动速度,优化的过程中要注意:

    控制线程数量 – 线程池

    检查线程间的锁 ,防止依赖等待

    使用合理的启动架构

    微信内部使用的 mmkernel

    阿里 Alpha

    五、业务梳理

    这里涉及到具体的业务,每个 App 都不一样,但是所要做的事情都是一样的,下面是邵文在高手课里面提到的:

    • 梳理清楚启动过程中的每一个模块,哪些是一定需要的,那些是可以砍掉,那些是可以懒加载的
    • 根据不同的业务场景决定不同的启动模式
    • 懒加载防止集中化,否则容易出现首页显示后用户无法操作的情形

    总的来说,用以下四个维度分整理启动的各个点

    • 必要且耗时:启动初始化,考虑用线程来初始化
    • 必要不耗时:首页绘制
    • 非必要但耗时:数据上报、插件初始化
    • 非必要不耗时:不用想,这块直接去掉,在需要用的时再加载

    一句话概述,要提高应用的启动速度,核心思想是在启动过程中少做事情,越少越好。

    六、业务优化

    通过梳理之后,剩下的都是启动过程一定要用的模块。这个时候,我们只能硬着头皮去做进一步的优化。优化前期需要“抓大放小”,先看看主线程究竟慢在哪里。最理想是通过算法进行优化,例如一个数据解密操作需要 1 秒,通过算法优化之后变成 10 毫秒。退而求其次,我们要考虑这些任务是不是可以通过异步线程预加载实现,但需要注意的是过多的线程预加载会让我们的逻辑变得更加复杂。业务优化做到后面,会发现一些架构和历史包袱会拖累我们前进的步伐。比较常见的是一些事件会被各个业务模块监听,大量的回调导致很多工作集中执行,部分框架初始化“太厚”,例如一些插件化框架,启动过程各种反射、各种 Hook,整个耗时至少几百毫秒。还有一些历史包袱非常沉重,而且“牵一发动全身”,改动风险比较大。但是我想说,如果有合适的时机,我们依然需要勇敢去偿还这些“历史债务”。

    相关文章

      网友评论

          本文标题:Android性能优化-启动优化

          本文链接:https://www.haomeiwen.com/subject/yazjkdtx.html