Android性能優(yōu)化之繪制優(yōu)化

前言


1 繪制原理

  • CPU負責(zé)計算顯示內(nèi)容
  • GPU負責(zé)柵格化(UI元素繪制到屏幕上)
  • 16ms發(fā)出VSync信號觸發(fā)UI渲染(90HZ屏幕是11ms)

2 優(yōu)化工具

  • Systrace
  • Layout Inspector
    Android studio自帶工具,可用來查看視圖層級。
  • Choreographer
    獲取App的FPS
public class FPSFrameCallback implements Choreographer.FrameCallback {

    private static final String TAG = "FPS_TEST";
    private long mLastFrameTimeNanos = 0;
    private long mFrameIntervalNanos;

    public FPSFrameCallback(long lastFrameTimeNanos) {
        mLastFrameTimeNanos = lastFrameTimeNanos;
        mFrameIntervalNanos = (long)(1000000000 / 60.0);
    }

    @Override
    public void doFrame(long frameTimeNanos) {
        //初始化時間
        if (mLastFrameTimeNanos == 0) {
            mLastFrameTimeNanos = frameTimeNanos;
        }
        final long jitterNanos = frameTimeNanos - mLastFrameTimeNanos;
        if (jitterNanos >= mFrameIntervalNanos) {
            final long skippedFrames = jitterNanos / mFrameIntervalNanos;
            if(skippedFrames>30){
                Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                        + "The application may be doing too much work on its main thread.");
            }
        }
        mLastFrameTimeNanos=frameTimeNanos;
        //注冊下一幀回調(diào)
        Choreographer.getInstance().postFrameCallback(this);
    }
}

在Appicaition的onCreate方法中使用

Choreographer.getInstance().postFrameCallback(new FPSFrameCallback(System.nanoTime()));

3 布局加載原理

3.1 布局加載流程

3.2 性能瓶頸

  • xml解析:IO過程
  • 創(chuàng)建View對象:反射

3.3 LayoutInflater.Factory

  • LayoutInflate創(chuàng)建View的一個Hook
  • 定制創(chuàng)建View的過程:全局替換自定義TextView等
    注意:在super.onCreate之前使用
LayoutInflaterCompat.setFactory2(layoutInflater, object : LayoutInflater.Factory2 {
            override fun onCreateView(
                parent: View?,
                name: String,
                context: Context,
                attrs: AttributeSet
            ): View? {
                if (TextUtils.equals("TextView", name)) {
                    //創(chuàng)建自定義View
                    val view1 = delegate.createView(parent, name, context, attrs)
                    return view1
                }
                return null
            }

            override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
                return null
            }

        })

4 獲取界面布局耗時

  • AspectJ獲取界面布局耗時
  • ARTHook實現(xiàn)
  • 獲取每一個空間的加載耗時
    注意:在super.onCreate之前使用
LayoutInflaterCompat.setFactory2(layoutInflater, object : LayoutInflater.Factory2 {
            override fun onCreateView(
                parent: View?,
                name: String,
                context: Context,
                attrs: AttributeSet
            ): View? {
                val startTime = System.currentTimeMillis()
                val view = delegate.createView(parent, name, context, attrs)
                val endTime = System.currentTimeMillis()
                Log.d("TAG", "{${endTime - startTime}}")
                return view
            }

            override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
                return null
            }

        })

5 布局加載優(yōu)化

5.1 AsyncLayoutInflater

?AsyncLayoutInflater能夠異步加載和解析xml,減少反射、I/O在主線程中的耗時情況。需要注意的是View不能在主線程進行操作。

class PerformanceActivity : AppCompatActivity() {
    private lateinit var button: Button
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        AsyncLayoutInflater(this).inflate(
            R.layout.activity_main, null
        ) { view, resid, parent ->
            setContentView(view)
            button = view.findViewById(R.id.button)
        }
//        主線程操作報錯
//        button.setOnClickListener { }
    }
}

5.2 Java代碼寫布局

  • 因為少了反射、I/O等操作,本質(zhì)上解決了性能問題,但是同時會產(chǎn)生不便于開發(fā)、可維護性差等問題。
    針對Java代碼寫布局不易維護等問題,我們可以使用第三方開源框架X2C,通過使用APT根據(jù)XML生成Java代碼。

總結(jié)

?繪制優(yōu)化的核心思想主要包括以下幾點

  • 使用Choreographer查看FPS
  • 使用ConstainLayout減少層級,可以通過Layout Inspector查看視圖層級
  • 使用LayoutInflater.Factory查看View繪制時間
  • 使用AsyncLayoutInflater或X2C提升XML加載效率
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容