这个问题似乎无处不在,过去两个半小时一直让我感到疯狂。我一直在互联网上寻找解决方案,但我的任务是徒劳的。
因此我决定寻求帮助。
我的Android游戏编译得很好,它曾经运行良好,但现在却没有。 它发生在我开始添加一些图片以供游戏使用的时候。
记录的消息:
01-28 20:42:34.510: WARN/dalvikvm(3857): threadid=10: thread exiting with uncaught exception (group=0x40015560)
01-28 20:42:34.510: ERROR/AndroidRuntime(3857): FATAL EXCEPTION: Thread-11
01-28 20:42:34.510: ERROR/AndroidRuntime(3857): java.lang.NullPointerException
01-28 20:42:34.510: ERROR/AndroidRuntime(3857): at com.ballbounce.bounce.MainGamePanel.update(MainGamePanel.java:153)
01-28 20:42:34.510: ERROR/AndroidRuntime(3857): at com.ballbounce.bounce.MainThread.run(MainThread.java:91)
01-28 20:42:34.510: WARN/ActivityManager(105): Force finishing activity com.ballbounce.bounce/.BallBounceActivity
我认为NullPointerException是由于线程退出而发生的,而不是线程关闭的实际原因。
我在Eclipse中试过'清理'项目,重新启动Eclipse,重新启动手机......所有常见的东西。我的“撤消”功能不会让我回到足够远的地方让游戏进入稳定的状态。
相关代码(我试图尽可能减少它):
BallBounceActivity.java
public class BallBounceActivity extends Activity {
// Trimmed down for ease-of-viewing
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
mainGamePanel = new MainGamePanel(this);
setContentView(mainGamePanel);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "BallBounceActivity");
}
protected void onPause() {
// Trimmed down for ease-of-viewing
}
protected void onResume() {
// Trimmed down for ease-of-viewing
}
protected void onStop() {
// Trimmed down for ease-of-viewing
}
private SensorEventListener accelerationListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int acc) {
}
@Override
public void onSensorChanged(SensorEvent event) {
// Trimmed down for ease-of-viewing
}
};
}
MainGamePanel.java
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback {
// Trimmed down for ease-of-viewing
private MainThread thread;
// The Fps to be displayed
private String avgFps;
public void setAvgFps(String avgFps) {
this.avgFps = avgFps;
}
public MainGamePanel(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
thread = new MainThread(getHolder(), this);
thread.setRunning(true);
thread.start();
random = new Random();
bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inScaled = false;
powerups = new Bitmap[12];
// Copy and paste time!
powerups[0] = BitmapFactory.decodeResource(getResources(), R.drawable.coin, bmpFactoryOptions);
powerups[1] = BitmapFactory.decodeResource(getResources(), R.drawable.powerup_8, bmpFactoryOptions);
powerups[2] = BitmapFactory.decodeResource(getResources(), R.drawable.powerup_9, bmpFactoryOptions);
// Trimmed down for ease-of-viewing
ballImages = new Bitmap[8];
// Copy and paste time!
ballImages[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ball_0, bmpFactoryOptions);
ballImages[1] = BitmapFactory.decodeResource(getResources(), R.drawable.ball_1, bmpFactoryOptions);
ballImages[2] = BitmapFactory.decodeResource(getResources(), R.drawable.ball_2, bmpFactoryOptions);
// Trimmed down for ease-of-viewing
items = new ArrayList<Item>();
theBall = new Ball(this.getWidth(), this.getHeight(), 24.0f, items, ballImages);
platform = new Platform(this.getWidth(), this.getHeight(), 180.0f);
player = new Player(theBall, platform);
theBall.setPlayer(player);
theBall.setPlatform(platform);
x = y = 0.0f;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Trimmed down for ease-of-viewing
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Trimmed down for ease-of-viewing
}
public void render(Canvas canvas) {
// Trimmed down for ease-of-viewing
}
public void update() {
// Trimmed down for ease-of-viewing
theBall.update(x, y);
platform.update();
}
public void updateAccelerometerValues(float x, float y, float z) {
// Trimmed down for ease-of-viewing
}
public void displayScore(Canvas canvas) {
// Trimmed down for ease-of-viewing
}
public void displayFps(Canvas canvas, String fps) {
// Trimmed down for ease-of-viewing
}
}
MainThread.java
public class MainThread extends Thread {
// Trimmed down for ease-of-viewing
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
@Override
public void run() {
Canvas canvas;
// Trimmed down for ease-of-viewing
sleepTime = 0;
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0;
this.gamePanel.update();
this.gamePanel.render(canvas);
timeDiff = System.currentTimeMillis() - beginTime;
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
this.gamePanel.update();
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
// Trimmed down for ease-of-viewing
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
Log.d(TAG, "Thread exited");
}
}
R.java
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int ball_0=0x7f020000;
public static final int ball_1=0x7f020001;
public static final int ball_2=0x7f020002;
public static final int ball_3=0x7f020003;
public static final int ball_4=0x7f020004;
public static final int ball_5=0x7f020005;
public static final int ball_6=0x7f020006;
public static final int ball_7=0x7f020007;
public static final int coin=0x7f020008;
public static final int ic_launcher=0x7f020009;
public static final int powerup_8=0x7f02000a;
public static final int powerup_9=0x7f02000b;
public static final int powerup_9_save=0x7f02000c;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}
如何解决这个问题的任何想法,甚至是关于如何发生的任何建议都将不胜感激。
非常感谢Will。
答案 0 :(得分:1)
我想出了一个解决方案:
在整个gamePanel.update()
函数完成之前,Thread-11调用了surfaceCreated(SurfaceHolder holder)
函数。这意味着Thread-11在初始化之前尝试使用对象,这当然会导致NullPointerException。
我的解决方法是添加:
while(gamePanel.player == null) {
try {
Thread.sleep(10);
}
catch (InterruptedException e) {}
}
在MainThread while (running) ...
函数的run()
位之前。 ('玩家'的选择是因为'玩家'是最后一个被初始化的对象。)
非常有趣的问题,也是一个有趣的解决方案。
我希望这个解决方案可以解决将来某些人的问题!