2015-04-06 56 views
0

我有一個簡單的應用程序,它通過嵌套在活動佈局中的SurfaceView在屏幕上顯示圖像。在方法中修改的Android變量不會在線程中更新

我有一個SurfaceViewExample類,它創建OurView的一個新實例,幷包含按鈕調用的方法。有三種方法:

  1. 第一種方法是arrowPressed(查看視圖),當按下三個箭頭鍵中的任何一個時,將調用該方法。它得到其中的按鈕調用它並傳遞的ID到
  2. arrowAction(OurView ourview,字符串方向),其調用
  3. moveImage(INT的xChange,INT yChange)與x和必要ÿ變化來移動所述圖像中那個方向。

    public void arrowPressed(View view) { 
        switch (view.getId()) { 
    
         case R.id.arrowLeft: 
          arrowAction(gameView, "left"); 
          break; 
    
         case R.id.arrowRight: 
          arrowAction(gameView, "right"); 
          break; 
    
         case R.id.arrowUp: 
          arrowAction(gameView, "up"); 
          break; 
        } 
    } 
    
    ------------------------------------------------------------------------------------ 
    
    void arrowAction(OurView ourView, String direction) { 
        switch (direction) { 
    
         case "left": 
          ourView.moveImage(-1,0); 
          break; 
    
         case "right": 
          ourView.moveImage(1,0); 
          break; 
    
         case "up": 
          ourView.moveImage(0,1); 
          break; 
        } 
    } 
    
    ------------------------------------------------------------------------------------ 
    
    void moveImage(int xChange, int yChange) { 
        xCoord = xCoord + xChange; 
        yCoord = yCoord + yChange; 
    } 
    

這一切似乎按預期方式工作。 moveImage被成功調用,它修改xCoord和yCoord變量。當我從moveImage中打印x和y Coords時,它們會反映它們的更改值。但是,moveImage中的xCoord和yCoord與線程MyThread中的xCoord和yCoord之間似乎存在脫節。

doDraw(Canvas canvas)方法在(xPos,yPos)處繪製位圖(這些變量只是調整x和y座標,以便圖像以座標點爲中心,而不是在左上角開啓該座標點)。當我用這種方法打印x和y Coords時,它們會反映原始值。

public void doDraw(Canvas canvas) { 
    xPos = xCoord - (testimg.getWidth()/2); 
    yPos = yCoord - (testimg.getHeight()/2); 
    canvas.drawBitmap(testimg, xPos, yPos, null); 
} 

我可以想到發生這種情況的唯一原因是moveImage創建了一個名爲xCoord和yCoord的新局部變量。然而,這是沒有道理的,因爲它成功地獲得了xCoord和yCoord的原始價值。

全碼:

SurfaceViewExample:

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.os.Bundle; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 

public class SurfaceViewExample extends Activity { 

    OurView gameView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     gameView = new OurView(this); 
     setContentView(R.layout.activity_surface_view_example); 
    } 

    public void arrowPressed(View view) { 
     switch (view.getId()) { 

      case R.id.arrowLeft: 
       arrowAction(gameView, "left"); 
       break; 

      case R.id.arrowRight: 
       arrowAction(gameView, "right"); 
       break; 

      case R.id.arrowUp: 
       arrowAction(gameView, "up"); 
       break; 
     } 
    } 

    void arrowAction(OurView ourView, String direction) { 
     switch (direction) { 

      case "left": 
       ourView.moveImage(-1,0); 
       break; 

      case "right": 
       ourView.moveImage(1,0); 
       break; 

      case "up": 
       ourView.moveImage(0,1); 
       break; 
     } 
    } 
} 

OurView:

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 

public class OurView extends SurfaceView implements SurfaceHolder.Callback { 

    private MyThread myThread; 
    private SurfaceHolder holder; 
    private Bitmap testimg; 
    public int xCoord = 500; 
    public int yCoord = 500; 
    int xPos; 
    int yPos; 

    public OurView(Context context) { 
     super(context); 
     init(); 
    } 

    public OurView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public OurView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    private void init() { 
     myThread = new MyThread(this); 

     holder = getHolder(); 
     holder.addCallback(this); 
     testimg = BitmapFactory.decodeResource(getResources(),R.drawable.testimg); 
    } 

    void moveImage(int xChange, int yChange) { 
     xCoord = xCoord + xChange; 
     yCoord = yCoord + yChange; 
     System.out.println("-----"); 
     System.out.println("-----"); 
     System.out.println(xCoord); 
     System.out.println(yCoord); 
     System.out.println("-----"); 
     System.out.println("-----"); 
    } 

    public void doDraw(Canvas canvas) { 
     System.out.println("Starting drawing..."); 
     System.out.println(xCoord); 
     System.out.println(yCoord); 
     xPos = xCoord - (testimg.getWidth()/2); 
     yPos = yCoord - (testimg.getHeight()/2); 
     System.out.println(xPos); 
     System.out.println(yPos); 
     canvas.drawBitmap(testimg, xPos, yPos, null); 
     System.out.println("Drawing finished."); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     myThread.setRunning(true); 
     myThread.start(); 
    } 

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

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     boolean retry = true; 
     myThread.setRunning(false); 

     while (retry) { 
      try { 
       myThread.join(); 
       retry = false; 
      } 

      catch (InterruptedException e) {} 
     } 
    } 

} 

MyThread的:

import android.graphics.Canvas; 

public class MyThread extends Thread{ 

    OurView myView; 
    private boolean running = false; 

    public MyThread(OurView view) { 
     myView = view; 
    } 

    public void setRunning(boolean run) { 
     running = run; 
    } 

    @Override 
    public void run() { 
     while(running){ 

      Canvas canvas = myView.getHolder().lockCanvas(); 

      if(canvas != null){ 
       synchronized (myView.getHolder()) { 
        myView.doDraw(canvas); 
       } 
       myView.getHolder().unlockCanvasAndPost(canvas); 
      } 

      try { 
       sleep(30); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 
    } 
} 

的MyThread的類幾乎是純粹的複製粘貼+從Create animation on SurfaceView in background Thread

回答

0

每次調用onDraw時,畫布對象形式MyThread都會更改。你不應該在其他類中引用Canvas。

+0

從MyThread引用畫布有什麼替代方法? – WD40

+0

使用主線程進行渲染,並在引用OurView類中所需對象的onDraw方法中繪製對象。 – yonutix