我正在尝试编写一个视频游戏,我想重新绘制背景以模拟地图。
所以为此,我创建了一个新的类,它扩展了surfaceview,一个扩展了一个线程,实现了我需要的所有(我的活动的xml文件中的surfaceview)。但是我有一个小问题,当我setcontentview
它自动崩溃时告诉我我有StackOverflowError
。
首先,我的主要活动代码
public class MainActivity extends Activity {
float debutX = -1;``
float debutY = -1;
float height = 0; // 1280
float width =0; // 720
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View img = (View) findViewById(R.id.img);
final TextView text = (TextView) findViewById(R.id.text);
final RelativeLayout parent = (RelativeLayout) findViewById(R.id.parent);
surface surf = (surface)findViewById(R.id.surface);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) parent.getLayoutParams();
surf=new surface(getApplicationContext());
setContentView(surf,params);
parent.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent ev) {
height=parent.getHeight();
width=parent.getWidth();
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
debutX=0;
debutY=0;
if (zonecorrecte(ev.getX(), ev.getY(), width, height)) {
debutX = ev.getX();
debutY = ev.getY();
text.setText(debutX + ", " + debutY);
}
break;
case MotionEvent.ACTION_MOVE:
float a = ((ev.getX() - debutX) / 2) + img.getX();
float b = (ev.getY() - debutY) / 2 + img.getY();
if (danslecranX(a, width, img)) {
img.setX(a);
}
if (danslecranY(b, height, img)) {
img.setY(b);
}
Log.d("Main", a + " " +b);
if(img.getX()<=0.2*width &&img.getY()<=0.2*height)
{}
try {
Thread.sleep(40);
} catch (InterruptedException e) {}
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
});
}
和新线程:
package tibo.test5;
@SuppressLint("WrongCall")
public class surface extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder surface = null;
DrawingThread mThread=new DrawingThread();
final View img = (View) findViewById(R.id.img);
Paint p = new Paint();
Bitmap caro = BitmapFactory.decodeResource(getResources(),R.drawable.caro);
public void onDraw(Canvas canvas) {
p.setAntiAlias(true);
p.setFilterBitmap(true);
p.setDither(true);
canvas.drawBitmap(caro, 0, 0, p);
draw(canvas);
}
public surface(Context context) {
super(context);
init();
mThread = new DrawingThread();
}
public void init() {
surface = getHolder();
surface.addCallback(this);
}
public surface(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
// TODO:
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mThread.keepDrawing = true;
mThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mThread.keepDrawing = false;
boolean joined = false;
while (!joined) {
try {
mThread.join();
joined = true;
} catch (InterruptedException e) {
}
}
}
class DrawingThread extends Thread {
boolean keepDrawing = true;
int deb = 0;
@Override
public void run() {
while (keepDrawing) {
Canvas canvas = null;
try {
canvas = surface.lockCanvas();
synchronized (surface) {
if(canvas!=null)onDraw(canvas);
}
} finally {
surface.unlockCanvasAndPost(canvas);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
}
我只是希望能够在需要时“刷新”我的表面,但是在第二次开始运行线程时我的游戏被冻结并崩溃无关紧要。
日志:
06-23 01:38:42.751: D/OpenGLRenderer(15394): Enabling debug mode 0 06-23 01:38:42.816: I/dalvikvm(15394): threadid=11: stack overflow on call to Landroid/graphics/Bitmap;.nativeConfig:II 06-23 01:38:42.816: I/dalvikvm(15394): method requires 4+20+0=24 bytes, fp is 0x61b65308 (8 left) 06-23 01:38:42.816: I/dalvikvm(15394): expanding stack end (0x61b65300 to 0x61b65000) 06-23 01:38:42.816: I/dalvikvm(15394): Shrank stack (to 0x61b65300, curFrame is 0x61b68fdc) 06-23 01:38:42.816: W/dalvikvm(15394): threadid=11: thread exiting with uncaught exception (group=0x41c75c08) 06-23 01:38:42.851: D/dalvikvm(15394): GC_FOR_ALLOC freed 145K, 15% free 8466K/9920K, paused 14ms, total 14ms 06-23 01:38:42.856: E/AndroidRuntime(15394): FATAL EXCEPTION: Thread-4458 06-23 01:38:42.856: E/AndroidRuntime(15394): Process: tibo.test5, PID: 15394 06-23 01:38:42.856: E/AndroidRuntime(15394): java.lang.StackOverflowError 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.graphics.Bitmap.getConfig(Bitmap.java:1302) 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.graphics.Bitmap.isPremultiplied(Bitmap.java:1148) 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1086) 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.graphics.Canvas.drawBitmap(Canvas.java:1139) 06-23 01:38:42.856: E/AndroidRuntime(15394): at tibo.test5.surface.onDraw(surface.java:29) 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.view.View.draw(View.java:15410) 06-23 01:38:42.856: E/AndroidRuntime(15394): at android.view.SurfaceView.draw(SurfaceView.java:349) 06-23 01:38:42.856: E/AndroidRuntime(15394): at tibo.test5.surface.onDraw(surface.java:30)
所以这是我没有得到的:
我是否处于无限循环中,因为我没有用reume()
/ pause()
处理我的线程,或者我的draw方法是否为图像重新分配内存而不删除某些内容?
我试图添加简历并停止但它没有用,所以我相信我的第二个理论是正确的。
答案 0 :(得分:0)
您正在进行无限递归(导致堆栈溢出),因为您正在draw()
方法中调用onDraw()
。而不是子类SurfaceView
,只需创建SurfaceHolder.Callback
的实例(或让Activity
或Fragment
实现接口)并保留SurfaceHolder
的实例。然后在您的主题中,您可以锁定Surface
,直接绘制到Canvas
,然后调用SurfaceHolder.unlockCanvasAndPost()
。