2016-03-15 53 views
0

我在做一個遊戲杆應用程序,點擊按鈕應該顯示一個列表視圖。但是,當我打開列表視圖時,應用程序會關閉關於具有空指針異常的畫布的錯誤消息,因此無法獲取畫布的寬度/高度。 錯誤:Android:canvas給出空指針異常 - 如何解決它?

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Canvas.getWidth()' on a null object reference 

代碼:

public class MySurfaceThread extends AsyncTask<Void, Void, Void>{ 

    SurfaceHolder mSurfaceHolder; 
    CustomSurfaceView cSurfaceView; 


    public MySurfaceThread(SurfaceHolder sh, CustomSurfaceView csv){ 
     mSurfaceHolder = sh; 
     cSurfaceView = csv; 
     x = y = 0; 

     cSurfaceView.setOnTouchListener(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       x = event.getX(); 
       y = event.getY(); 
       System.out.println(x + " " + y); 

       calculateValues(x,y); 

       switch (event.getAction() & MotionEvent.ACTION_MASK){ 
        case MotionEvent.ACTION_DOWN: 
         break; 
        case MotionEvent.ACTION_UP: 
         x = y = 0; 
         dx = dy = 0; 
         break; 
        case MotionEvent.ACTION_CANCEL: 
         break; 
       } 
       return true; 
      } 

      private void calculateValues(float xx, float yy){ 
       dx = xx-zeroX; 
       dy = yy-zeroY; 
       angle = (float)Math.atan(Math.abs(dy/dx)); 
       c = (float)Math.sqrt(dx * dx + dy * dy); 

       if(c > radius){ 
        if (dx > 0 && dy > 0) { //lower right corner 
         xx = (float) (zeroX + radius * Math.cos(angle)); 
         yy = (float) (zeroY + radius * Math.sin(angle)); 
        } 
        else if(dx > 0 && dy < 0){ //top right corner 
         xx = (float) (zeroX + radius * Math.cos(angle)); 
         yy = (float) (zeroY - radius * Math.sin(angle)); 
        } 
        else if(dx < 0 && dy < 0){ //top left corner 
         xx = (float) (zeroX - radius * Math.cos(angle)); 
         yy = (float) (zeroY - radius * Math.sin(angle)); 
        } 
        else if(dx < 0 && dy > 0){ //lower left corner 
         xx = (float) (zeroX - radius * Math.cos(angle)); 
         yy = (float) (zeroY + radius * Math.sin(angle)); 
        } 
       } 
       else { 
        xx = zeroX + dx; 
        yy = zeroY + dy; 
       } 
       System.out.println("dx: " + dx); 
       System.out.println("dy: " + dy); 
       x = xx; 
       y = yy; 
      } 
     }); 


    } 


    //@Override 
    protected Void doInBackground(Void... params) { 


     while(run) { 



      Canvas canvas = new Canvas(); 
      canvas.drawBitmap(background,0,0,null); 
      cSurfaceView.surfaceCreated(mSurfaceHolder); 



      try { 

       canvas = mSurfaceHolder.lockCanvas(null); 

       synchronized (mSurfaceHolder) { 

        zeroX = (1704-1704/8); 
        zeroY = (915-915/4); 
        cSurfaceView.onDraw(canvas, x, y, zeroX, zeroY); 

       } 
       Thread.sleep(10); 
      } catch (InterruptedException e) { 

      } finally { 
       if (canvas != null) { 
        mSurfaceHolder.unlockCanvasAndPost(canvas); 
       } 

      } 
     } 
     return null; 
    } 
} 

而且,如果需要的話 - 繼承人的onDraw方法:

protected void onDraw(Canvas canvas, float x, float y, float zx, float zy){ 

    dx = x-zx; 
    dy = y-zy; 

    super.onDraw(canvas); 

    canvas.drawRGB(255, 255, 255); 
    canvas.drawBitmap(background, (canvas.getWidth() - canvas.getWidth()/7) - background.getWidth()/2, (canvas.getHeight() - canvas.getHeight()/4) - background.getHeight()/2, null); 
    canvas.drawText(Float.toString(x), 60, 60, paint1); 
    canvas.drawText(Float.toString(y), 60, 120, paint1); 

    if (x == 0 && y == 0) { 
     canvas.drawBitmap(ball, (canvas.getWidth()-canvas.getWidth()/7) - ball.getWidth()/2, (canvas.getHeight()-canvas.getHeight()/4) - ball.getHeight()/2, null); 

    } 
    else { 
     canvas.drawBitmap(ball, x - ball.getWidth()/2, y - ball.getHeight()/2, null); 
    } 
} 

你們是否有任何想法如何,我可以初始化畫布爲了它的工作?

欣賞我所能得到的所有幫助!

+0

根據文檔:如果曲面尚未創建或以其他方式無法編輯,則返回null。你通常需要實現Callback.surfaceCreated來找出Surface何時可用。要麼它在尚未創建時被破壞。在表面準備好之前,您不應該運行此線程,並且在表面被破壞時將其殺死。 –

+0

感謝您的回覆@gabesechan, 我仍然不確定如何檢查表面是否已創建。 到目前爲止,我已經嘗試在Callback.surfaceCreated中執行以下操作: public void surfaceCreated(SurfaceHolder arg0){ Surface surface = arg0.getSurface(); if(arg0!= null)thread.execute(); } } –

回答

0

感謝Gabe的解釋,我得到它與回調以下代碼一起工作。

public void surfaceCreated(SurfaceHolder arg0) { 
    Surface surface = arg0.getSurface(); 


    if (surface != null){ 
     thread.execute((Void[])null); 
    } 


} 

public void surfaceDestroyed(SurfaceHolder arg0) { 

    thread.cancel(true); 

} 

通過下面的評論,我實現了創建表面,只要它被破壞時(一個新的框架中打開時,在這種情況下)的線程來執行線程被取消的方式。

乾杯!