Android 绘图 Bitmap.createScaledBitmap 冻结 UI;

问题描述 投票:0回答:1

我注意到当我使用

Bitmap.createScaledBitmap(...)
使我的位图适合屏幕,绘制它并移动我的表面视图时,我的应用程序冻结(ANR)但是如果我
Bitmap.createScaledBitmap(...)
使用较小的尺寸一切正常,但我希望这些位图适合屏幕。我用标签将这段代码加粗,这是问题所在。我想知道如何解决这个问题?

Loader.java

public static Map<Integer, Bitmap[]> differentFramesMap = new HashMap<>();
public static Map<Integer, Canvas[]> differentCanvasesMap = new HashMap<>();

private static void init(List<Integer> animFrames, TileMapData t) {
    for (int i = 0; i < animFrames.size(); i++) {
        differentFramesMap.put(i, new Bitmap[animFrames.get(i)]);
        differentCanvasesMap.put(i, new Canvas[animFrames.get(i)]);
        for (int j = 0; j < animFrames.get(i); j++) {
            differentFramesMap.get(i)[j] = Bitmap.createBitmap(t.width * t.tilewidth, t.height * t.tileheight, Bitmap.Config.ARGB_8888);
            differentCanvasesMap.get(i)[j] = new Canvas(differentFramesMap.get(i)[j]);
        }
    }
}



public static void createBitmaps(TileMapData t, int startLayer, int endLayer, GameSurface gameSurface) {

    try {
        AssetManager assetManager = gameSurface.getContext().getAssets();

        Bitmap[] tilesets = new Bitmap[t.tilesets.size()];

        for (int i = 0; i < tilesets.length; i++) {
            tilesets[i] = BitmapFactory.decodeStream(assetManager.open(t.tilesets.get(i).ImageFilename));
        }

        long currentGID;
        Long localGID;
        Integer currentTileSetIndex;
        Rect source = new Rect(0, 0, 0, 0);
        Rect dest = new Rect(0, 0, 0, 0);

        for (int i = startLayer; i < endLayer; i++) {
            for (int j = 0; j < t.layers.get(i).height; j++) {
                for (int k = 0; k < t.layers.get(i).width; k++) {

                    currentGID = t.getGIDAt(k, j, i);
                    localGID = t.getLocalID(currentGID);
                    currentTileSetIndex = t.getTileSetIndex(currentGID);

                    if (!isAfterInit) {
                        animFrames = Stream.of(t.tilesets.get(currentTileSetIndex).tileAnimations)
                                .map(tileAnimation -> tileAnimation.getTileFrames().size()).collect(Collectors.toList());

                        init(animFrames, t, gameSurface);
                        isAfterInit = true;
                    }

                    if (localGID != null) {
                        if (i == startLayer) {
                            (...)                               
                        } else {
                            for (int l = 0; l < t.tilesets.get(currentTileSetIndex).tileAnimations.size(); l++) {

                                if (localGID == t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getLocalGID()) {
                                    for (int frame = 0; frame < t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().size(); frame++) {

                                        source.top = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() / ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tileheight);
                                        source.left = (int) ((t.tilesets.get(currentTileSetIndex).tileAnimations.get(l).getTileFrames().get(frame).getTileId() % ((t.tilesets.get(currentTileSetIndex).imageWidth) / t.tilewidth)) * t.tilewidth);
                                        source.bottom = source.top + t.tileheight;
                                        source.right = source.left + t.tilewidth;

                                        dest.top = j * t.tileheight;
                                        dest.left = k * t.tilewidth;
                                        dest.bottom = dest.top + t.tileheight;
                                        dest.right = dest.left + t.tilewidth;

                                        differentCanvasesMap.get(l)[frame].drawBitmap(tilesets[currentTileSetIndex], source, dest, new Paint());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        for (int i = 0; i < differentFramesMap.size(); i++) {
            for (int j = 0; j < animFrames.get(i); j++) {

                    **HERE IS THE PROBLEM**
                    differentFramesMap.get(i)[j] = Bitmap.createScaledBitmap(differentFramesMap.get(i)[j], gameSurface.getCellWidth() * t.width, gameSurface.getCellHeight() * t.height, false);
            }
        }
    } catch (IOException e) {
        Log.e(TAG, e.getMessage());
    }
}


public static void drawTmxMaps(Canvas canvas) {
    canvas.drawBitmap(differentFramesMap.get(0)[framesFirstAnimIter], 0, 0, null);
    canvas.drawBitmap(differentFramesMap.get(1)[framesSecondAnimIter], 0, 0, null);
    canvas.drawBitmap(differentFramesMap.get(2)[framesThirdAnimIter], 0, 0, null);

    if (!isIterStarted) {
        iterTmxFrames();
        isIterStarted = true;
    }
}



private static void iterTmxFrames() {
    runnable = () -> {
        framesFirstAnimIter++;
        framesSecondAnimIter++;
        framesThirdAnimIter++;
        if (framesFirstAnimIter == 3)
            framesFirstAnimIter = 0;
        if (framesSecondAnimIter == 2)
            framesSecondAnimIter = 0;
        if (framesThirdAnimIter == 2)
            framesThirdAnimIter = 0;
        handler.postDelayed(runnable, 1000);
    };
    handler.postDelayed(runnable, 1000);
}

GameMainSurface.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    //HERE IS WHERE APP STOPS RESPONDING
    if (ev.getAction() == MotionEvent.ACTION_UP) {
        setX(100);
    }
    return true;
}
java android surfaceview
1个回答
0
投票

很难说到底发生了什么,因为我们看不到那些静态函数在哪里被调用。但是缩放位图很昂贵。如果你必须做很多,不要在主线程上做。在另一个线程上执行,然后将消息发送到主线程并绘制结果。

© www.soinside.com 2019 - 2024. All rights reserved.