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