Tôi đang cố triển khai SurfaceView
, gọi phương thức onDraw()
từ số Thread
, dựa trên this tutorial. Ứng dụng của tôi đang cung cấp ANR sau khi tôi bắt đầu chạy mã bên dưới.tại sao runnable của tôi cho ANR?
Tôi đã thử implementing Runnable, thay vì mở rộng Thread
nhưng vẫn cung cấp ANR.
Theo như tôi biết there's nothing else running trên ứng dụng khi ANR xảy ra. (ANR chỉ bắt đầu xảy ra khi tôi thêm mã này :)
package com.thunderrabbit.run;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MainThread extends Thread {
private final String TAG = this.getClass().getSimpleName();
// desired fps
private final static int MAX_FPS = 50;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000/MAX_FPS;
private SurfaceHolder surfaceHolder;
private PageGLSurfaceView gamePanel;
private boolean running; // flag to hold game state
private Canvas canvas;
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
public MainThread(SurfaceHolder surfaceHolder, MySurfaceView gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
sleepTime = 0;
while(running)
{
canvas = null;
try
{
synchronized (surfaceHolder)
{
canvas = surfaceHolder.lockCanvas();
beginTime = System.currentTimeMillis();
// resetting the frames skipped
framesSkipped = 0;
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
// calculate how long did the cycle take
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
// update without rendering
this.gamePanel.update();
// add frame period to check if in next frame
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
beginTime = System.currentTimeMillis();
gamePanel.onDraw(canvas);
}
}
finally
{
if (canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
// update game state
// render state to the screen
}
DebugLog.d(TAG, "Game loop executed ");
}
}
Điều gì gây ra ANR? Tôi có nên triển khai Runnable
hoặc mở rộng Thread
theo cách khác không?
Nếu thread UI bị chặn trong hơn một vài giây người dùng sẽ được trình bày với các khét tiếng "ứng dụng không phản hồi" (ANR) hộp thoại. Bạn có biết về "Activity.runOnUiThread (Runnable)" không? Tôi nghĩ rằng đây sẽ là giải pháp của bạn. –
Bạn có thể đăng Logcat không? –
@Balaji Tôi đã thấy runOnUiThread, nhưng quên nó trong trường hợp này. Ngoài ra, xin lỗi tôi đã không thể đăng đầu ra LogCat; Tôi về cơ bản đã giải quyết nó trước khi gây ra vấn đề một lần nữa. :-) –