android性能优化--布局优化


布局展示要保证16ms 发出vsync信号触发UI渲染一帧。

1.1 Systrace

关注frame

1.2 Layout Inspector

在这里插入图片描述

1.3 Choregrapher

获取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);
            }
        });
    }

1.4 打开开发者选项–过度绘制

开发者选项里–》调式GPU过度绘制功能,然后回到APP内,如果有过度绘制界面会显示深红色。然后结合其他形式,调式UI 结构。
如设置控件的背景色,又设置了控件的图片,就会引起过度绘制。

1.过多重叠的背景

2.过多叠加的View—如果有叠加的自定义view,可以通过代码指定绘制区域。

canvas.clipRect(mCardLeft,0,mCardLeft+mCardSpacing,mDroidCards.get(i).getHeight());

3.复杂的Layout层级

解决办法:
1.移除Window默认的background:getWidow.setBackgroundDrawable(null); 移除XML布局中非必要的background
2.扁平化视图,减少布局嵌套,减少View数的深度,减少遍历渲染时间,使用约束布局,相对布局等
3.使用ViewStub。
4.使用include+merge

1.5 使用X2C形式加载布局

首先你需要了解布局加载原理:https://blog.csdn.net/chentaishan/article/details/108609347
默认的加载布局的本质其实就是加载XML文件,设计IO的读写,也是属于优化的方向。

1.6 使用AOP获取界面加载时间

execution 监测整个方法内部执行完毕
android.app.Activity.setContentView 监听setContentView方法

    @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));
    }

1.7 获取每个控件的耗时

放到setContentView之前 ,当真正加载布局的时候,会触发Factory2的实现类的拦截逻辑。

   LayoutInflaterCompat.setFactory2(getLayoutInflater(), new LayoutInflater.Factory2() {
            @Override
            public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {

                //拦截固定组件,打印组件的创建需要的时间,根据时间来得知创建当前view的时长。
                if (TextUtils.equals(name, "TextView")) {
                    // 生成自定义TextView
              
                long time = System.currentTimeMillis();
                View view = getDelegate().createView(parent, name, context, attrs);
                LogUtils.i(name + " cost " + (System.currentTimeMillis() - time));
                }
                return view;
            }

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

1.8 AsyncLayoutInflater 异步加载

常规布局加载有两个问题,读取布局文件慢 :IO 过程 ;反射过程慢 :使用new 创建

1.导入依赖

 implementation 'com.android.support:asynclayoutinflater:28.0.0-alpha1'

2.如何使用

  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);
                mRecyclerView = findViewById(R.id.recycler_view);
                mRecyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
                mRecyclerView.setAdapter(mNewsAdapter);
                mNewsAdapter.setOnFeedShowCallBack(MainActivity.this);
            }
        });

详细查看源码分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值