private float eastYStart = 300f;
private float eastXEnd = 450;
private float eastYEnd = 300;
private float southeastXStart = 335.36f;
private float southeastYStart = 335.34f;
private float southeastXEnd = 406.10f;
private float southeastYEnd = 406.02f;
private float southXStart = 300.03f;
private float southYStart = 345f;
private float southXEnd = 300;
private float southYEnd = 450;
private float southwestXStart = 264.68f;
private float southwestYStart = 335.39f;
private float southwestXEnd = 194.06f;
private float southwestYEnd = 406.19f;
private float westXStart = 250;
private float westYStart = 300;
private float westXEnd = 150;
private float westYEnd = 300;
String colorStr[] = new String[]{
“#ffff00”,
“#ff3300”,
“#ccff00”,
“#ff00cc”,
“#ccffff”,
“#cc99ff”,
“#99ff66”,
“#993300”
};
private ValueAnimator valueAnimator;
private int currentColor = 0;
public IOSStyleLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
this.mStrokeWidth = UIUtils.dp2px(this.mContext, 5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Sample test1=new Sample(“测试1”);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(this.mStrokeWidth);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
Path p0 = new Path();
paint.setColor(Color.parseColor(colorStr[0]));
p0.moveTo(northwestXStart, northwestYStart);
p0.lineTo(northwestXEnd, northwestYEnd);
canvas.drawPath(p0, paint);
Path p1 = new Path();
paint.setColor(Color.parseColor(colorStr[1]));
p1.moveTo(northXStart, northYStart);
p1.lineTo(northXEnd, northYEnd);
canvas.drawPath(p1, paint);
Path p2 = new Path();
paint.setColor(Color.parseColor(colorStr[2]));
p2.moveTo(notheastXStart, notheastYStart);
p2.lineTo(notheastXEnd, notheastYEnd);
canvas.drawPath(p2, paint);
Path p3 = new Path();
paint.setColor(Color.parseColor(colorStr[3]));
p3.moveTo(eastXStart, eastYStart);
p3.lineTo(eastXEnd, eastYEnd);
canvas.drawPath(p3, paint);
Path p4 = new Path();
paint.setColor(Color.parseColor(colorStr[4]));
p4.moveTo(southeastXStart, southeastYStart);
p4.lineTo(southeastXEnd, southeastYEnd);
canvas.drawPath(p4, paint);
Path p5 = new Path();
paint.setColor(Color.parseColor(colorStr[5]));
p5.moveTo(southXStart, southYStart);
p5.lineTo(southXEnd, southYEnd);
canvas.drawPath(p5, paint);
Path p6 = new Path();
paint.setColor(Color.parseColor(colorStr[6]));
p6.moveTo(southwestXStart, southwestYStart);
p6.lineTo(southwestXEnd, southwestYEnd);
canvas.drawPath(p6, paint);
Path p7 = new Path();
paint.setColor(Color.parseColor(colorStr[7]));
p7.moveTo(westXStart, westYStart);
p7.lineTo(westXEnd, westYEnd);
canvas.drawPath(p7, paint);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
startAnimation();
}
public void startAnimation() {
valueAnimator = ValueAnimator.ofInt(7, 0);
valueAnimator.setDuration(400);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if ((int) animation.getAnimatedValue() != currentColor){
String b[] = new String[colorStr.length];
for (int c = 0, size = colorStr.length - 1; c < size; c++) {
b[c + 1] = colorStr[c];
}
b[0] = colorStr[colorStr.length - 1];
colorStr = b;
invalidate();
currentColor = (int) animation.getAnimatedValue();
}
}
});
valueAnimator.start();
}
}
内存分配
这是一个看起来相对平滑的内存走势图,但是也能看出内存一直在增加,不知道为什么我的内存分配Allocations一直为0,希望看到的小伙伴留言解答一下。
上面的代码有三个问题:
1、不断创建String对象,如下代码
paint.setColor(Color.parseColor(color[0]));
点击进去看源码:
public static int parseColor(@Size(min=1) String colorString) {
if (colorString.charAt(0) == ‘#’) {
// Use a long to avoid rollovers on #ffXXXXXX
// 这里调用了String类的substring方法
long color = Long.parseLong(colorString.substring(1), 16);
if (colorString.length() == 7) {
// Set the alpha value
color |= 0x00000000ff000000;
} else if (colorString.length() != 9) {
throw new IllegalArgumentException(“Unknown color”);
}
return (int)color;
} else {
Integer color = sColorNameMap.get(colorString.toLowerCase(Locale.ROOT));
if (color != null) {
return color;
}
}
throw new IllegalArgumentException(“Unknown color”);
}
原来这里调用了String类的substring方法,我们都知道String类是不可变类,每一个字符串对应一个String对象,每次调用substring方法截取字符串就要新建一个String对象来接收截取后的值,所以我们选中的String对象就来自这里。
代码修改如下:
int[] colorInt = new int[colorStr.length];
// 构造方法中初始化
for (int i = 0; i < colorStr.length; i++) {
colorInt[i] = Color.parseColor(colorStr[i]);
}
2、不能再onDraw中创建对象
Path mPath = new Path();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 把Paint、Path的创建移出去
mPath.reset();
paint.setColor(colorInt[(currentColor++)%8]);
mPath.moveTo(northwestXStart, northwestYStart);
mPath.lineTo(northwestXEnd, northwestYEnd);
canvas.drawPath(mPath, paint);
}
3、属性动画的addUpdateListener监听中不断创建数组
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if ((int) animation.getAnimatedValue() != currentColor){
// 记录每次回调的int值,去改变颜色的角标
currentColor = (int) animation.getAnimatedValue();
invalidate();
}
}
});
通过修改,内存非常稳定,没有了大量对象的创建。那我们来看一下是否有内存泄漏的问题呢?
使用Profiler工具dump一下,查看内存分配的具体信息,在使用MAT工具查看明细。
查看Activity是否有强引用
可以看到我们刚刚的自定义菊花Activity退出后一直存在强引用,造成内存泄漏。Activity的Context一直被自定义控件持有,再往上看IOSStyleLoadingView
又IOSStyleLoadingView$1
内部类持有。
引用关系
注意:
动画一直要记得停止
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (valueAnimator != null){
valueAnimator.removeAllUpdateListeners();
valueAnimator.cancel();
}
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-9E6DPKMy-1715884249405)]
[外链图片转存中…(img-NAmxGXZm-1715884249406)]
[外链图片转存中…(img-vWtNzBgo-1715884249407)]
[外链图片转存中…(img-M4S77LPu-1715884249408)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!