【问题标题】:Android slow canvas behavior when drawing bitmaps绘制位图时Android缓慢的画布行为
【发布时间】:2016-11-18 20:13:19
【问题描述】:

我正在为 android 开发一个家庭 brew family guy 角色创建器。基本上你可以为你的角色选择头发、胡须、衬衫、裤子等。我正在使用复合图案来存储当前佩戴的面部特征和衣服。我正在使用画布来显示用户正在创建的自定义角色的当前状态。当我的活动开始时,画布会立即绘制 3 个位图,但之后当用户单击(触摸)一种头发类型时,由于某种原因(有时甚至长达 1 分钟),绘制需要非常长的时间。我似乎找不到任何合理的解释来解释为什么会发生这种情况。提前致谢。

我的 onCreate 重写方法的一部分:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_play);

character = new Character();
character.attach(this); //observes the character

assetManager = getAssets();
BitmapLoader.setAssetManager(assetManager);

/*...*/

characterView = (LinearLayout) findViewById(R.id.character_view);

initCanvas();
initButtons();
loadPersistedCharacter();

character.notifyAllObservers(); //just for testing purposes
}

我的画布初始化代码:

private void initCanvas() {
    Paint paint = new Paint();
    Bitmap background = Bitmap.createBitmap(600, 800, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(background);

    paint.setColor(Color.parseColor("#CD5C5C"));
    characterView.setBackground(new BitmapDrawable(getResources(), background));
}

当通过使用观察者模式点击衣服或面部特征(在 onClickListeners 的帮助下)时,会调用更新方法,该方法可以在与之前代码相同的 Activity 中找到。

@Override
public void update() {
    Paint paint = new Paint();
    Skin skin = character.getSkin();
    Bitmap bitmap = BitmapLoader.load(skin.getPath());

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

float scale = skin.getScale();
int asd = bitmap.getWidth();
int asdY = bitmap.getHeight();

float coordX = (canvas.getWidth() - scale * asd) / skin.getXPosDivider();
float coordY = (canvas.getHeight() - scale * asdY) / skin.getYPosDivider();

RectF rect= new RectF(coordX, coordY, coordX + scale * bitmap.getWidth(), coordY + scale * bitmap.getHeight());

canvas.drawBitmap(bitmap, null, rect, paint);

for (HeadFeature feature : character.getHeadFeatures()) {
    scale = feature.getScale();
    bitmap = BitmapLoader.load(feature.getPath());

    coordX = (canvas.getWidth() - scale * bitmap.getWidth()) / feature.getXPosDivider();
    coordY = (canvas.getHeight() - scale * bitmap.getHeight()) / feature.getYPosDivider();

    rect= new RectF(coordX, coordY, coordX + scale * bitmap.getWidth(), coordY + scale * bitmap.getHeight());

    canvas.drawBitmap(bitmap, null, rect, paint);
}
}

【问题讨论】:

  • 您是在 SurfaceView 上绘图吗?我没有看到任何需要一分钟才能绘制的特别费力的东西。此外,如果您在主线程上绘图,您会遇到 ANR 崩溃(但在 SurfaceView 线程上绘图不会导致这种情况)。
  • 还有一些小的优化,如果你不在每个绘制周期创建像PaintRectF 这样的新对象,你将获得更好的性能。将它们隐藏在类级别并使用它们的 setter 方法更新它们。
  • 感谢您的提示。我没有使用 SurfaceView,而是使用简单的 LinearLayout。我尝试使用 SurfaceView 但从未调用过 onSurfaceCreated 回调。加上 SurfaceView 我无法使背景透明。我不认为我收到了 ANR 崩溃,只是出于某种奇怪的原因没有立即绘制它。绘图发生在我猜的主线程上。
  • 使用 RGB_565 而不是 ARGB_8888,因为 ARGB_8888 每个像素占用 4 个字节并编码 RGB + alpha 通道,而 RGB_565 每个像素使用 2 个字节并且只编码 RGB,但质量问题不大。试一试
  • 我已经尝试过了。我什至尝试设置 android:hardwareAccelerated="true" 并有所帮助,但效果不大。

标签: android canvas bitmap


【解决方案1】:

问题如下:我的 characterView LinearLayout 从未失效,因此很少刷新。应用程序根本不知道我的视图应该被刷新。对 characterView.invalidate() 的简单调用解决了这个问题。

public void update() {
    /*...*/
    characterView.invalidate();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多