Android高手笔记-屏幕适配 & UI优化

2022-02-23  本文已影响0人  今阳说

Android高手笔记-屏幕适配 & UI优化

屏幕与适配

适配方式:

px

dp

宽高限定符适配

鸿洋的AndroidAutoLayout适配方案等动态计算UI适配框架

smallestWidth适配 或者叫sw限定符适配

今日头条适配方案

UI优化

CPU 与 GPU

OpenGL 与 Vulkan

1. 画笔:Skia 或者 OpenGL。我们可以用 Skia 画笔绘制 2D 图形,也可以用 OpenGL 来绘制 2D/3D 图形。正如前面所说,前者使用 CPU 绘制,后者使用 GPU 绘制。
2. 画纸:Surface。所有的元素都在 Surface 这张画纸上进行绘制和渲染。在 Android 中,Window 是 View 的容器,每个窗口都会关联一个 Surface。
而 WindowManager 则负责管理这些窗口,并且把它们的数据传递给 SurfaceFlinger。
3. 画板:Graphic Buffer。Graphic Buffer 缓冲用于应用程序图形的绘制,在 Android 4.1 之前使用的是双缓冲机制;在 Android 4.1 之后,使用的是三缓冲机制。
4. 显示:SurfaceFlinger。它将 WindowManager 提供的所有 Surface,通过硬件合成器 Hardware Composer 合成并输出到显示屏。

Android 渲染的演进

  1. 在 Android 3.0 之前,或者没有启用硬件加速时,系统都会使用软件方式来渲染 UI;
  2. Androd 3.0 开始,Android 开始支持硬件加速;
  3. Android 4.0 时,默认开启硬件加速;
  4. Android 4.1:
    1. 开启了Project Butter: 主要包含两个组成部分,一个是 VSYNC,一个是 Triple Buffering。VSYNC信号:对于 Android 4.0,CPU 可能会因为在忙别的事情,导致没来得及处理 UI 绘制。 为解决这个问题,Project Buffer 引入了VSYNC,它类似于时钟中断。每收到 VSYNC 中断,CPU 会立即准备 Buffer 数据,由于大部分显示设备刷新频率都是 60Hz(一秒刷新 60 次),也就是说一帧数据的准备工作都要在 16ms 内完成。三缓冲机制 Triple Buffering:Android 4.1 之前,Android 使用双缓冲机制,CPU、GPU 和显示设备都能使用各自的缓冲区工作,互不影响
    2. Android 4.1还新增了 Systrace 性能数据采样和分析工具。
    3. Tracer for OpenGL ES 也是 Android 4.1 新增加的工具,它可逐帧、逐函数的记录 App 用 OpenGL ES 的绘制过程。它提供了每个 OpenGL 函数调用的消耗时间,所以很多时候用来做性能分析。但因为其强大的记录功能,在分析渲染问题时,当 Traceview、Systrace 都显得棘手时,还找不到渲染问题所在时,此时这个工具就会派上用场了。
  5. Android 4.2,系统增加了检测绘制过度工具;
  6. Android 5.0:RenderThread:
    • 经过 Project Butter 黄油计划之后,Android 的渲染性能有了很大的改善。但是不知道你有没有注意到一个问题,虽然我们利用了 GPU 的图形高性能运算,但是从计算 DisplayList,到通过 GPU 绘制到 Frame Buffer,整个计算和绘制都在 UI 主线程中完成。
    • Android 5.0 引入了两个比较大的改变。一个是引入了 RenderNode 的概念,它对 DisplayList 及一些 View 显示属性做了进一步封装。另一个是引入了 RenderThread,所有的 GL 命令执行都放到这个线程上,渲染线程在 RenderNode 中存有渲染帧的所有信息,可以做一些属性动画,这样即便主线程有耗时操作的时候也可以保证动画流畅。
    • 还可以开启 Profile GPU Rendering 检查。
  7. Android 6.0 ,在 gxinfo 添加了更详细的信息;
  8. 在 Android 7.0 又对 HWUI 进行了一些重构,而且支持了 Vulkan;
  9. 在 Android P 支持了 Vulkun 1.1。

UI 渲染测量

1. gfxinfo

2. SurfaceFlinger

获取界面布局耗时

  1. AOP
@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();
    }
    LogHelper.i(name + " cost " + (System.currentTimeMillis() - time));
}
  1. LayoutInflaterCompat.setFactory2
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

    // 使用LayoutInflaterCompat.Factory2全局监控Activity界面每一个控件的加载耗时,
    // 也可以做全局的自定义控件替换处理,比如:将TextView全局替换为自定义的TextView。
    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();
            // 1
            View view = getDelegate().createView(parent, name, context, attrs);
            LogHelper.i(name + " cost " + (System.currentTimeMillis() - time));
            return view;
        }

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

    // 2、setFactory2方法需在super.onCreate方法前调用,否则无效
    super.onCreate(savedInstanceState);
    setContentView(getLayoutId());
    unBinder = ButterKnife.bind(this);
    mActivity = this;
    ActivityCollector.getInstance().addActivity(this);
    onViewCreated();
    initToolbar();
    initEventAndData();
}

UI优化的常用手段

1. 尽量使用硬件加速

2. Create View 优化

3. measure/layout 优化

参考文章

上一篇 下一篇

猜你喜欢

热点阅读