2015-04-06 57 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