2012-10-30 132 views
2

我創建了一個Android應用程序,它在屏幕上繪製一個小圖像並在屏幕的底部50px點擊時退出。當我點擊它時,它會退出,但是,當我按下後退(或主頁)按鈕退出應用程序時,它退出,但接着說:「不幸的是,遊戲開發已停止。」我還檢查了LogCat,它顯示每次停止工作時都會發生Java NullPointerException。從logcat的輸出是:按下後退按鈕後Android應用程序無法工作

10-30 01:13:28.280: E/AndroidRuntime(15294): FATAL EXCEPTION: Thread-1718 
10-30 01:13:28.280: E/AndroidRuntime(15294): java.lang.NullPointerException 
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameView.onDraw(GameView.java:56) 
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameThread.run(GameThread.java:30) 

我有三個Java類:Game.java(活動),GameView.java(在SurfaceView),和GameThread.java(主線程)。

的代碼如下:

Game.java:

package tricrose.gamedev; 

import android.os.Bundle; 
import android.app.Activity; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.Menu; 
import android.view.Window; 
import android.view.WindowManager; 

public class Game extends Activity { 

    public static final String TAG = Game.class.getSimpleName(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     setContentView(new GameView(this)); 
     Log.d(TAG, "View added"); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.activity_game, menu); 
     return true; 
    } 
} 

GameView.java:

package tricrose.gamedev; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class GameView extends SurfaceView implements SurfaceHolder.Callback { 

    public static final String TAG = GameView.class.getSimpleName(); 
    private GameThread thread; 

    public GameView(Context context) { 
     super(context); 
     getHolder().addCallback(this); 
     thread = new GameThread(getHolder(), this); 
     setFocusable(true); 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     thread.setRunning(true); 
     thread.start(); 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     boolean retry = true; 
     while (retry) { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (Exception e) {} 
     } 
    } 

    public boolean onTouchEvent(MotionEvent e) { 
     if (e.getAction() == MotionEvent.ACTION_DOWN) { 
      if (e.getY() > getHeight() - 60) { 
       thread.setRunning(false); 
       ((Activity)getContext()).finish(); 
      } 
     } 
     return super.onTouchEvent(e); 
    } 

    protected void onDraw(Canvas canvas) { 
     canvas.drawColor(Color.BLACK); 
     canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null); 
    } 
} 

GameThread.java:

package tricrose.gamedev; 

import android.graphics.Canvas; 
import android.view.SurfaceHolder; 

public class GameThread extends Thread { 

    public static final String TAG = GameThread.class.getSimpleName(); 
    private boolean running; 
    private SurfaceHolder surfaceHolder; 
    private GameView gameView; 

    public GameThread(SurfaceHolder surfaceHolder, GameView gameView) { 
     super(); 
     this.surfaceHolder = surfaceHolder; 
     this.gameView = gameView; 
    } 

    public void setRunning(boolean running) { 
     this.running = running; 
    } 

    public void run() { 
     Canvas canvas; 
     while (running) { 
      canvas = null; 
      try { 
       canvas = this.surfaceHolder.lockCanvas(); 
       synchronized (surfaceHolder) { 
        this.gameView.onDraw(canvas); 
       } 
      } finally { 
       if (canvas != null) { 
        surfaceHolder.unlockCanvasAndPost(canvas); 
       } 
      } 
     } 
    } 
} 

我已經搜索整個互聯網爲解決方案,我找不到一個實際工作,所以任何幫助非常感謝。

回答

0

你爲什麼要從onDraw和GameThread的兩個地方繪製run方法。我認爲你需要刪除onDraw只做GameThread rlun方法的每個繪圖。

+0

我只在GameView類中進行繪圖,但是如果從GameThread類中移除它,onDraw函數將永遠不會被調用。我嘗試了它,並且因爲它是GameThread中調用onDraw函數的循環,所以圖像沒有出現。 – Tristram

+0

不要嘗試從GameThread調用onDraw,將繪圖代碼放在運行中,並刪除onDraw,這是沒有必要的。 –

+0

這是一個非常好的主意,雖然它不起作用,因爲每次線程循環時都會調用相同的代碼,無論它是否在onDraw函數中。所以,不幸的是,它沒有奏效。 – Tristram

0

這只是一個猜測,但您的應用程序可能仍然在繪製,而應用程序正試圖退出。在你的onDraw方法調用這行代碼(這可能是你的問題的原因):
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
在這種情況下,你可能沒有可用的resuorces了;)

你可以嘗試:
1 。把一類的私人位圖變量到您的GameView類:
private Bitmap mBitmap;
2.將位圖在GameView構造:
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.droid_1);
3.繪製使用(已加載)位圖:
canvas.drawBitmap(mBitmap, 10, 10, null);

希望有所幫助!

+0

感謝您的建議,但不幸的是它沒有奏效。我認爲你是對的,線程不會在應用程序結束時結束,所以它會拋出NullPointerException,儘管在GameView類中創建私有位圖仍然會導致相同的錯誤。 雖然真的有很好的建議! – Tristram

+0

這是一個醜陋的事情,但如果你只是想過去這個問題,你可以把它放在你的onDraw方法中:'code'try {/ *你在這裏繪製代碼* /} catch(NullPointerException e){Log。 e(「MyTAG」,「忽略NPE」,e);} – Peter

2

我終於設法找到解決方案!事實證明,我應該在調用onDraw之前檢查canvas是否爲null,如果它爲null,則通過完成活動退出應用程序。我在JavaCodeGeeks.com上找到了解決方案,在那裏我正在看Android教程。感謝大家的所有答案!

相關問題