我一直在为Android开发一种游戏引擎,但我有一些严重的稳定性问题。
我使用SurfaceView
和已实现的Runnable
进行多线程处理,以获得我的主/ UI线程的一些工作。该类的简化版如下所示:
private class MenuView extends SurfaceView implements Runnable
{
Thread T = null;
SurfaceHolder holder;
Canvas c;
boolean run;
public MenuView(Context context) {
super(context);
holder = getHolder();
}
@Override
public void run() {
while(run)
{
if(!holder.getSurface().isValid())
{
continue;
}
c = holder.lockCanvas();
//Doing updates and drawing stuff
holder.unlockCanvasAndPost(c);
}
}
public void pause()
{
run = false;
try
{
T.join();
}
catch (InterruptedException e)
{
Log.e("Error:", "joining thread failed!");
}
}
public void resume()
{
run = true;
T = new Thread(this);
T.start();
}
//bunch of helper methods with no effect on this problem :(
}
正如你所看到的,我的“Worker”线程被一个由“run”boolean控制的无限while循环捕获,并且这个boolean是使用onPause()中调用的pause()和resume()方法设置的我的活动的onResume()方法如下所示:
MenuView menuV;
Random Rand = new Random();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Screen = getRealScreenSize(getApplicationContext());
menuV = new MenuView(this);
menuV.setOnTouchListener(this);
logoV = new LogoView(this);
setContentView(logoV); Log.d("APP", "SET LOGO VIEW");
//^ This is my splash screen, again irrelevant to the issue, after few seconds of running, this view calls the resume() of my SurfaceView and sets it as the contentView.
}
@Override
protected void onPause() {
super.onPause();
Log.d("APP", "ON PAUSE");
menuV.pause();
}
@Override
protected void onResume() {
super.onResume();
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
//^hides the goddamn navigation bar...
Log.d("APP", "ON RESUME");
menuV.resume();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
Log.d("APP", "ON TOUCH DOWN");
for(int i = 0; i < menuV.button.length ; i++)
{
if(menuV.button[i].active)
{
if(event.getX() > menuV.button[i].pos.left && event.getX() < menuV.button[i].pos.right && event.getY() > menuV.button[i].pos.top && event.getY() < menuV.button[i].pos.bottom)
{
menuV.button[i].pressed = true;
return true;
}
}
}
}
else if(event.getAction() == MotionEvent.ACTION_UP)
{
Log.d("APP", "ON TOUCH UP");
for(int i = 0; i < menuV.button.length ; i++)
{
menuV.button[i].pressed = false;
}
}
return false;
}
所以我的触摸事件由UI线程处理,但它正在访问工作线程一直在使用的信息,同样的事情发生在onPause()和onResume()上,UI线程正在改变“运行” “工作线程总是使用的布尔值,我这样说是因为看起来ANR在触摸屏幕时以及断电和打开电话时都会发生。渲染并没有停止,似乎工作线程很好,但UI线程很糟糕,它停止响应,这条线显示在我的Android监视器上:
线程[2,tid = 18257,WaitingInMainSignalCatcherLoop,Thread * = 0x558cbf1310,peer = 0x12c470a0,“Signal Catcher”]:对信号3作出反应
将堆栈跟踪写入'/data/anr/traces.txt'
如果有任何其他有用的信息,请告诉我 - 我会在此行之后编辑您指出的重要信息,谢谢!
答案 0 :(得分:0)
尝试将run
变量标记为volatile:
volatile boolean run;
也许你有与缓存相关的问题。