我正在编写我的第一个安卓游戏。它几乎在每个方面都运行良好,但是当屏幕超时开始并且我按下按钮返回游戏时,我发现游戏状态的图像卡住了。看起来主线程仍然存在 - 我可以这么说是因为当我在屏幕上拖动某些对象时会发出一组声音,并且声音仍然表现得好像一切正常(除了我除了卡住屏幕)。如果我然后选择一个菜单来显示“高分” Activity ,然后退出回到游戏,我发现一切都很好并且可以继续所有图形正常工作。
我不太确定我的代码的哪些部分需要包含以诊断此问题,但这是我的猜测 - 如果需要,我会添加更多内容:
编辑:在 Brigham 的建议下,我对代码做了几个修改,但症状是一样的。
编辑: 我注意到,如果我单击一个按钮来启动“查看高分” Activity ,则会调用 surfaceDestroyed()。但是当屏幕超时开始时,不会调用 surfaceDestroyed()。
编辑: 有很多人对此问题没有解决方案 - 我认为这个问题一定非常棘手 - 或者可能没有在我发布的代码 fragment 中揭示。关于我如何诊断这个问题的一些建议将非常有用。
编辑:我现在将整个(简化的)项目放在 simple.zip 中,并将其放在网上:http://dl.dropbox.com/u/2969211/Simple.zip - 关键代码都在文件 simple.java 中
MicksPanelThing mpt = null;
public MicksThreadThing micks_thread_thing = null;
@Override
protected void onPause() // pair with onResume
{
super.onPause();
allow_draw.set(false);
micks_thread_thing.setRunning(false);
save_state();
}
@Override
protected void onResume() // pair with onPause
{
super.onResume();
get_state();
mpt.get_a_new_thread_all_over_again();
micks_thread_thing.setRunning(true);
allow_draw.set(true);
}
////////////////////////////////////////////////////////////////////////////
public class MicksPanelThing extends SurfaceView implements SurfaceHolder.Callback
{
public MicksPanelThing(Context context)
{
super(context);
}
public void get_a_new_thread_all_over_again()
{
getHolder().addCallback(this);
micks_thread_thing = new MicksThreadThing(getHolder(), this);
setFocusable(true);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
synchronized (micks_thread_thing.getSurfaceHolder())
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
// blah
}
if (event.getAction() == MotionEvent.ACTION_MOVE && selected_node != -1)
{
// blah
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
// blah
}
return true;
}
}
@Override
public void onDraw(Canvas canvas)
{
canvas_width = canvas.getWidth();
canvas_height = canvas.getHeight();
if (allow_draw.get())
{
canvas.drawBitmap(sandy_bitmap, 0, 0, null);
// blah
}
}
public void surfaceCreated(SurfaceHolder holder)
{
micks_thread_thing.setRunning(true);
micks_thread_thing.start();
we_have_a_surface = true;
}
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
micks_thread_thing.setRunning(false);
while (retry)
{
try
{
micks_thread_thing.join();
retry = false;
micks_thread_thing = null;
}
catch (InterruptedException e)
{
// we will try it again and again...
}
}
we_have_a_surface = false;
}
}
class MicksThreadThing extends Thread
{
private SurfaceHolder surf_holder = null;
private MicksPanelThing micks_panel_thing;
private boolean this_thread_is_currently_active = false;
public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
{
surf_holder = surfaceHolder;
micks_panel_thing = mpt;
}
public void setRunning(boolean set_run)
{
this_thread_is_currently_active = set_run;
}
public SurfaceHolder getSurfaceHolder()
{
return surf_holder;
}
@Override
public void run()
{
Canvas c;
while (this_thread_is_currently_active)
{
c = null;
try
{
c = surf_holder.lockCanvas(null);
synchronized (surf_holder)
{
micks_panel_thing.onDraw(c);
}
}
finally
{
if (c != null)
{
surf_holder.unlockCanvasAndPost(c);
}
}
}
}
}
public class Allow_draw
{
private boolean draw;
Allow_draw()
{
draw = false;
}
public void set(boolean x)
{
synchronized (this)
{
draw = x;
}
}
boolean get()
{
synchronized (this)
{
return draw;
}
}
}
最佳答案
您的问题是您保留了 surf_holder
,因为您的线程成员 witch 是错误的。当您的 Activity 进入休眠状态然后返回时,Surface Holder 正在发生变化,它也可能发生在屏幕旋转或其他 SurfaceView 事件上。因此,最佳做法是每次要绘制时从 View 中询问它。
@Override
public void run()
{
Canvas c;
while (this_thread_is_currently_active)
{
c = null;
try
{
Final SurfaceHolder holder = getHolder();
c = holder.lockCanvas(null);
if(c != null)// may happen when SurfaceHolder is changing
synchronized (surf_holder)
{
micks_panel_thing.onDraw(c);
}
}
}
finally
{
if (c != null)
{
surf_holder.unlockCanvasAndPost(c);
}
}
}
}
不不不不!你做错了!
删除您获得的所有 SurfaceHolder 引用,不要将其保存在任何地方,删除您用于获取持有人的函数,也将其从您的线程中删除!。仅当您要锁定 Canvas 时才执行此操作:
//inside surfaceView
public void updateView(){
final SurfaceHolder holder = getHolder();
try{
Canvas canvas = holder.lockCanvas();
if(canvas != null){
onDraw(canvas);
}
holder.unlockCanvasAndPost(canvas);
}
catch (Exception e) {
// TODO: handle exception
}
}
关于android - onPause/onResume 后无法绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8821448/