You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化Android自定义View代码,使Profiler内存图表平滑

问题分析与优化方案

内存陡增+频繁GC的根源

  1. 无限循环重绘:自定义View的draw()方法中调用invalidate(),导致View持续触发重绘(每秒约60次),characterCreator.draw()被高频执行。
  2. Bitmap重复创建且未回收:每次调用characterCreator.draw()时,都会通过Bitmap.createScaledBitmap()生成新的Bitmap对象,旧的imageResized Bitmap未被回收,大量内存被重复占用,进而触发频繁GC。

具体优化步骤

1. 终止无限重绘

移除CharacterCreatorView.draw()中的invalidate()调用,改用可控的动画逻辑触发重绘:

  • 如果是帧动画场景,用Handler或ValueAnimator控制重绘间隔(比如每秒24/30帧),避免无意义的高频刷新。
    修改后的CharacterCreatorView.java示例:
@Override
public void draw(Canvas canvas) {
    super.draw(canvas);
    if(characterCreator != null)
        characterCreator.draw(canvas);
}

// 用Handler控制动画帧更新节奏
private final Handler animationHandler = new Handler(Looper.getMainLooper());
private final Runnable animationRunnable = new Runnable() {
    @Override
    public void run() {
        // 这里写切换动画帧的逻辑(比如更新colUsing)
        characterCreator.updateFrame();
        invalidate();
        animationHandler.postDelayed(this, 1000/30); // 30帧每秒
    }
};

// 启动动画
public void startAnimation() {
    animationHandler.post(animationRunnable);
}

// 停止动画
public void stopAnimation() {
    animationHandler.removeCallbacks(animationRunnable);
}

2. 提前预缩放Bitmap,避免重复创建

不在draw()方法中创建Bitmap,而是在初始化或切换动画帧/方向时完成缩放,并及时回收旧Bitmap:
修改CharacterCreator.java示例:

// 直接绘制预缩放好的Bitmap,不再在draw里创建新对象
public void draw(Canvas canvas) {
    canvas.drawBitmap(imageResized, 0, 0, null);
}

// 切换帧时调用,负责更新缩放后的Bitmap并回收旧对象
public void updateFrame() {
    Bitmap currentBitmap = getCurrentMoveBitmap();
    if (currentBitmap != null && !currentBitmap.equals(imageResized)) {
        // 回收旧Bitmap释放内存
        if (imageResized != null && !imageResized.isRecycled()) {
            imageResized.recycle();
        }
        // 缩放新帧的Bitmap
        imageResized = Bitmap.createScaledBitmap(currentBitmap, 300, 300, false);
    }
}

// 初始化时预加载第一帧的缩放Bitmap
public CharacterCreator(Bitmap baseSprite) {
    this.image = baseSprite;
    this.widthAllCols = image.getWidth();
    this.heightAllRows = image.getHeight();
    this.widthOneFrame = this.widthAllCols / 13;
    this.heightOneFrame = this.heightAllRows / ROW_COUNT;

    this.topToBottoms = new Bitmap[COL_COUNT];
    this.rightToLefts = new Bitmap[COL_COUNT];
    this.leftToRights = new Bitmap[COL_COUNT];
    this.bottomToTops = new Bitmap[COL_COUNT];

    // 初始化第一帧的缩放对象
    Bitmap firstBitmap = getMoveBitmaps()[0];
    imageResized = Bitmap.createScaledBitmap(firstBitmap, 300, 300, false);
}

3. 补充:Bitmap全生命周期内存管理

当CharacterCreator不再被使用时,主动回收所有Bitmap资源,避免内存泄漏:

public void release() {
    recycleBitmapArray(leftToRights);
    recycleBitmapArray(rightToLefts);
    recycleBitmapArray(topToBottoms);
    recycleBitmapArray(bottomToTops);
    if (imageResized != null && !imageResized.isRecycled()) {
        imageResized.recycle();
    }
    if (image != null && !image.isRecycled()) {
        image.recycle();
    }
}

private void recycleBitmapArray(Bitmap[] bitmaps) {
    if (bitmaps == null) return;
    for (Bitmap bmp : bitmaps) {
        if (bmp != null && !bmp.isRecycled()) {
            bmp.recycle();
        }
    }
}

内容的提问来源于stack exchange,提问作者user19516326

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:50:24