Android布局优化

Andorid 布局优化

  • 工具选择
    • Systrace
    • Layout inspector 查看控件层级
    • Choreographer 获取fps
  • Android 布局加载原理
  • 获取layout界面布局耗时
      • AOP方式
      • ARTHook实现
  • 获取layout里面单个view的耗时时间
  • AsyncLayoutInflater 异步Inflat
  • X2C 优化布局
  • 视图绘制

工具选择

Systrace

  • 关注Frams
  • 正常绿色 ,丢帧黄色或者红色
  • Alerts栏 会有修改建议

Layout inspector 查看控件层级

Choreographer 获取fps

  • 获取FPS ,线上使用 ,具备实时性
  • API 16+
    private long mStartFrameTime = 0;
    private int mFrameCount = 0;
    private static final long MONITOR_INTERVAL = 160L; //单次计算FPS使用160毫秒
    private static final long MONITOR_INTERVAL_NANOS = MONITOR_INTERVAL * 1000L * 1000L;
    private static final long MAX_INTERVAL = 1000L; //设置计算fps的单位时间间隔1000ms,即fps/s;
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void getFPS() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            return;
        }
        Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                if (mStartFrameTime == 0) {
                    mStartFrameTime = frameTimeNanos;
                }
                long interval = frameTimeNanos - mStartFrameTime;
                if (interval > MONITOR_INTERVAL_NANOS) {
                    double fps = (((double) (mFrameCount * 1000L * 1000L)) / interval) * MAX_INTERVAL;
                    mFrameCount = 0;
                    mStartFrameTime = 0;
                } else {
                    ++mFrameCount;
                }

                Choreographer.getInstance().postFrameCallback(this);
            }
        });
    }

Android 布局加载原理

Android布局优化_第1张图片

  • 导致布局性能的原因
    • 布局文件解析 : IO过程
    • 创建View对象 : 反射
  • LayoutInflater.Factory
    • LayoutInflater创建View的一个Hook
    • 定制创建View的过程
  • Factory2 extend Factory

获取layout界面布局耗时

AOP方式

  • 切Activity的setContentView

@Around(“execution(*android.app.Activity.setContentView(…))”)

// call        切在方法调用的位置
// execution   切在方法执行的位置
@Around("execution(* android.app.Activity.setContentView(..))")
    public void getSetContentViewTime(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String name = signature.toShortString();
        long time = System.currentTimeMillis();
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        LogUtils.i(name + " cost " + (System.currentTimeMillis() - time));
    }

ARTHook实现

获取layout里面单个view的耗时时间

  • 在 super.onCreate(savedInstanceState);之前
 LayoutInflaterCompat.setFactory2(getLayoutInflater(), new LayoutInflater.Factory2() {
            @Override
            public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {

                if (TextUtils.equals(name, "TextView")) {
                    // 生成自定义TextView
                }
                long time = System.currentTimeMillis();
                View view = getDelegate().createView(parent, name, context, attrs); //view控件创建完成
                LogUtils.i(name + " cost " + (System.currentTimeMillis() - time));
                return view;
            }

            @Override
            public View onCreateView(String name, Context context, AttributeSet attrs) {
                return null;
            }
        });
       super.onCreate(savedInstanceState);

AsyncLayoutInflater 异步Inflat

  • WorkThred加载布局 ,布局加载完成回调主线程渲染
  • implementation ‘com.android.support:asynclayoutinflater:28.0.0-alpha1’
new AsyncLayoutInflater(MainActivity.this).inflate(R.layout.activity_main, null, new AsyncLayoutInflater.OnInflateFinishedListener() {
            @Override
            public void onInflateFinished(@NonNull View view, int i, @Nullable ViewGroup viewGroup) {
                setContentView(view);
                // todo findViewById(id);
                TextView tv =  findViewById(R.id.tv);
            }
        });

X2C 优化布局

  • APT编译器翻译xml为java代码
  • annotationProcessor ‘com.zhangyue.we:x2c-apt:1.1.2’
  • implementation ‘com.zhangyue.we:x2c-lib:1.0.6’
  • @Xml(layouts = “activity_main”) 类注解 layout文件名
  • X2C.setContentView(MainActivity.this,R.layout.activity_main); 替换 setContentView(view);

视图绘制

  • 流程
    • 测量
    • 布局
    • 绘制
  • 布局层级优化
    • 优先选用ConstraintLayout布局
    • merge标签使用
  • 过度绘制优化
    • 去掉多余的背景设置
    • 控件叠加
    • 自定义控件开发时, 使用clipRect屏蔽被遮盖的布局
    • 开发者选项打开 “调试GPU过度绘制”
  • 其它技巧
    • Viewstub :占位符,延迟初始化
    • onDraw(): 避免绘制太大对象

你可能感兴趣的:(Android)