Android Curv Gradient 曲线渐层2-优化篇

前言

延续前篇Android Curv Gradient 曲线渐层
过了一个月...终於改好啦!!!!

效率比较

机型:同样使用Oppo R17 Pro
绘制数量:190个
监控工具:FPS监测工具 wasabeef/Takt
监控工具这边说明一下,前篇有提到在这样的测试条件下会有明显的卡顿问题,因此想到最直观的检测结果应该就是用FPS吧,但实际开发一开始是使用AndroidProfiler,监控记忆体以及物件的状况,大概类似下面这样,可以从记忆体走势、物件创建状况为参考,逐一去排除可能造成卡顿的问题。
https://ithelp.ithome.com.tw/upload/images/20210506/20126774vcilFa6Q9Z.png

首先我做一个一基准,先全部用TextView观察整个使用状况(由於这边不支援Gif,有兴趣请点外部连结出去看)
操作过程
生成RecyclerView FPS:2.3
快速滑动FPS:22.6 ~ 60
除了一看开使生成RecyclerView有些微卡顿,在使用中感觉不出卡顿

接下来使用旧版的也就是前篇未优化的版本
生成RecyclerView FPS:7.5
快速滑动FPS:2.6 ~ 7.5
操作过程

优化版
生成RecyclerView FPS:1.3
快速滑动FPS:17.2 ~ 51.3
操作过程

从数据部分可以看到在按下Load钮,生成RecyclerView即便用完全原生的TextView也是会有明显的卡顿状况,但是为何使用旧版的相比起来反而FPS比较高,我後来又测试了多次,三个版本大约都落在10FPS内,所以就不多探究这个部分。
快速滑动过程应该不用看数据就可以感觉到旧版有明显的卡顿,FPS部分也确实有明显的落差。

实际优化方案

发想

初期也是看了Profiler里面,会产生大量的物件,特别是Point, LinearGradient。Point改用两组Integer完全没有改善,LinearGradient又省不了,本来重复使用LinearGradient,至於mPositions参数的变化用反射的方式修改,但没试出来。一气之下就打算用改用JNI试试,主要是过去有个经验,把一模一样逻辑从Java搬到C直接快3倍,虽然有点麻烦但直觉肯定会变快。

实作

由於主要是要解决大量Java物件产生的问题,因此就只有在Java层取的一些基本设定,还有UI尺寸之後就直接送到C去计算以及渲染。计算部分流程都相同,主要差别在於LinearGradient直线渲染部分必须要自行解决

以下程序码是从原始码native-lib.cpp里面撷取,有兴趣请直接到Github查看

将从Java传过来的int color转为RGB

int* color0 = new int[3];
color0[0] = *tmpColor >> 16 & 0xff;
color0[1] = *tmpColor >> 8 & 0xff;
color0[2] = *tmpColor & 0xff;
//整张图的尺寸
int* tmpArray = new int[width * height];
for(int j = 0; j < width; j++) {
    //渐变点的座标
    int centerPosition = ((float) height)  * fullPositions[j];
    for (int i = 0; i < height; i++) {
        int red, green, blue;
        //计算每个Pixel颜色
        if(i < centerPosition) {
            float ratio = (float)i / (float)centerPosition;
            red = color0[0] + ((float)(color1[0] - color0[0]) * ratio);
            green = color0[1] + ((float)(color1[1] - color0[1]) * ratio);
            blue = color0[2] + ((float)(color1[2] - color0[2]) * ratio);
        }
        else{
            int secondHalf = height - centerPosition;
            float ratio = (float)(i - centerPosition) / (float)secondHalf;
            red = color1[0] + ((float)(color2[0] - color1[0]) * ratio);
            green = color1[1] + ((float)(color2[1] - color1[1]) * ratio);
            blue = color1[2] + ((float)(color2[2] - color1[2]) * ratio);
        }
        tmpArray[i * width + j] = 255 << 24 | (red << 16) | (green << 8) | blue;
    }
}

透过上面的程序码已经将所有Pixel的颜色都填好了,接下来就是回到Java的部分产生Bitmap并且绘制就完成了

Bitmap bmp = Bitmap.createBitmap(tmpArray, width, height, Bitmap.Config.ARGB_8888);
canvas.drawBitmap(bmp, 0, 0, paint);

结论

优化部分大致做到这个阶段,用起来还算顺畅了,由於平常没什麽机会写C,程序码应该还有很大的优化空间,但制哨初步的目的达到了,有空再来改写


<<:  使用档案救援软件是否安全?

>>:  Wentz QOTD CISSP练习题原创声明

Day 13 ( 中级 ) 平衡灯 ( 姿势 )

平衡灯 ( 姿势 ) 教学原文参考:平衡灯 ( 姿势 ) 这篇文章会介绍如何使用「当姿势发生」、「重...

[Day10 - UI/UX] 上传UI至 Zeplin

当我们画完UI後,接着要将UI上传到Zeplin 点选 Plugins > Browse 搜寻...

Java学习之路08---方法

架构图 方法简介 甚麽是方法 方法就是用来解决特殊需求的一个功能模块、程序语句的集合,把需要重复使用...

[NestJS 带你飞!] DAY22 - MongoDB

通常写後端都会使用到资料库,透过资料库来储存使用者相关的资料,而资料库有非常多种,本篇将会介绍最热门...

[PoEAA] Data Source Architectural Pattern - Active Record

本篇同步发布於个人Blog: [PoEAA] Data Source Architectural P...