我有一個簡單的應用程序,它通過嵌套在活動佈局中的SurfaceView在屏幕上顯示圖像。在方法中修改的Android變量不會在線程中更新
我有一個SurfaceViewExample類,它創建OurView的一個新實例,幷包含按鈕調用的方法。有三種方法:
- 第一種方法是arrowPressed(查看視圖),當按下三個箭頭鍵中的任何一個時,將調用該方法。它得到其中的按鈕調用它並傳遞的ID到
- arrowAction(OurView ourview,字符串方向),其調用
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。
從MyThread引用畫布有什麼替代方法? – WD40
使用主線程進行渲染,並在引用OurView類中所需對象的onDraw方法中繪製對象。 – yonutix