Android - “线程退出与未捕获的异常(组= 0x40015560)”

时间:2012-01-28 21:35:46

标签: java android

这个问题似乎无处不在,过去两个半小时一直让我感到疯狂。我一直在互联网上寻找解决方案,但我的任务是徒劳的。

因此我决定寻求帮助。

我的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。

1 个答案:

答案 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()位之前。 ('玩家'的选择是因为'玩家'是最后一个被初始化的对象。)

非常有趣的问题,也是一个有趣的解决方案。

我希望这个解决方案可以解决将来某些人的问题!