android– 为什么SurfaceView的onTouchEvent被叫几秒延迟?

概述我有一个非常简单的游戏SurfaceView,有时游戏几秒钟内没有响应触摸事件,然后它立即响应所有这些触摸事件.我已经在GalaxyS3和Nexus4上测试了我的游戏,它工作正常,似乎这个问题只发生在GalaxyS5上.>主要活动:publicclassDroidzActivityextendsActivity{/**Calledwhent

我有一个非常简单的游戏SurfaceVIEw,有时游戏几秒钟内没有响应触摸事件,然后它立即响应所有这些触摸事件.我已经在galaxy S3和Nexus 4上测试了我的游戏,它工作正常,似乎这个问题只发生在galaxy S5上.

>主要活动:

public class DroIDzActivity extends Activity {/** Called when the activity is first created. */private static final String TAG = DroIDzActivity.class.getSimplename();@OverrIDepublic voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    // requesting to turn the Title OFF    requestwindowFeature(Window.FEATURE_NO_Title);    // making it full screen    getwindow().setFlags(WindowManager.LayoutParams.FLAG_FulLSCREEN, WindowManager.LayoutParams.FLAG_FulLSCREEN);    // set our MainGamePanel as the VIEw    setContentVIEw(new MainGamePanel(this));    Log.d(TAG, "VIEw added");}@OverrIDeprotected voID onDestroy() {    Log.d(TAG, "Destroying...");    super.onDestroy();}@OverrIDeprotected voID onStop() {    Log.d(TAG, "StopPing...");    super.onStop();}     }

> MainGamePanel

公共类MainGamePanel扩展SurfaceVIEw实现SurfaceHolder.Callback {

private static final String TAG = MainGamePanel.class.getSimplename();private MainThread thread;public MainGamePanel(Context context) {    super(context);    // adding the callback (this) to the surface holder to intercept events    getHolder().addCallback(this);    // create the game loop thread    thread = new MainThread(getHolder(), this);    // make the GamePanel focusable so it can handle events    setFocusable(true);}@OverrIDepublic voID surfaceChanged(SurfaceHolder holder, int format, int wIDth,        int height) {}@OverrIDepublic voID surfaceCreated(SurfaceHolder holder) {    // at this point the surface is created and    // we can safely start the game loop    thread.setRunning(true);    thread.start();}@OverrIDepublic voID surfaceDestroyed(SurfaceHolder holder) {    Log.d(TAG, "Surface is being destroyed");    // tell the thread to shut down and wait for it to finish    // this is a clean shutdown    boolean retry = true;    while (retry) {        try {            thread.setRunning(false);            thread.join();            retry = false;        } catch (InterruptedException e) {            // try again shutting down the thread        }    }    Log.d(TAG, "Thread was shut down cleanly");}public voID render(Canvas canvas){    if(canvas!=null)        canvas.drawcolor(colorList[colorIndex]);}@OverrIDepublic boolean ontouchEvent(MotionEvent event) {    if (event.getAction() == MotionEvent.ACTION_DOWN) {        colorIndex++;        colorIndex = colorIndex % colorList.length;    }    return super.ontouchEvent(event);}int [] colorList = {color.RED, color.GREEN, color.BLUE, color.GRAY};    int colorIndex = 0;}

> MainThread

公共类MainThread扩展Thread {

private static final String TAG = MainThread.class.getSimplename();// Surface holder that can access the physical surfaceprivate SurfaceHolder surfaceHolder;// The actual vIEw that handles inputs// and draws to the surfaceprivate MainGamePanel gamePanel;// flag to hold game state private boolean running;public voID setRunning(boolean running) {    this.running = running;}public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {    super();    this.surfaceHolder = surfaceHolder;    this.gamePanel = gamePanel;}// desired fpsprivate final static int    MAX_FPS = 50;   // maximum number of frames to be skippedprivate final static int    MAX_FRAME_SKIPS = 5;    // the frame periodprivate final static int    FRAME_PERIOD = 1000 / MAX_FPS;  @OverrIDepublic voID run() {    Canvas canvas;    Log.d(TAG, "Starting game loop");    long beginTime;     // the time when the cycle begun    long timeDiff;      // the time it took for the cycle to execute    int sleepTime;      // ms to sleep (<0 if we're behind)    int framesSkipped;  // number of frames being skipped     sleepTime = 0;    while (running) {        canvas = null;        // try locking the canvas for exclusive pixel editing        // in the surface        try {            canvas = this.surfaceHolder.lockCanvas();            synchronized (surfaceHolder) {                beginTime = System.currentTimeMillis();                framesSkipped = 0;  // resetting the frames skipped                // update game state             //  this.gamePanel.update();                // render state to the screen                // draws the canvas on the panel                this.gamePanel.render(canvas);                              // calculate how long dID the cycle take                timeDiff = System.currentTimeMillis() - beginTime;                // calculate sleep time                sleepTime = (int)(FRAME_PERIOD - timeDiff);                if (sleepTime > 0) {                    // if sleepTime > 0 we're OK                    try {                        // send the thread to sleep for a short period                        // very useful for battery saving                        Thread.sleep(sleepTime);                        } catch (InterruptedException e) {}                }                while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {                    // we need to catch up                    // update without rendering                //  this.gamePanel.update();                     // add frame period to check if in next frame                    sleepTime += FRAME_PERIOD;                      framesSkipped++;                }            }        } finally {            // in case of an exception the surface is not left in             // an inconsistent state            if (canvas != null) {                surfaceHolder.unlockCanvasAndPost(canvas);            }        }   // end finally    }}   

}

这是应用程序最简单的版本,我已经尝试过,我可以再次重现同样的问题.它还有时需要5到10秒才能在S5上加载,而在Nexus 4和S3上加载的时间不到1秒.

解决方法:

看起来MainThread正在使UI线程挨饿.

最终执行的代码(删除了大量内容)如下所示:

canvas = this.surfaceHolder.lockCanvas();// Do a ton of stuffsurfaceHolder.unlockCanvasAndPost(canvas);canvas = this.surfaceHolder.lockCanvas();// Do a ton of stuffsurfaceHolder.unlockCanvasAndPost(canvas);canvas = this.surfaceHolder.lockCanvas();// Do a ton of stuffsurfaceHolder.unlockCanvasAndPost(canvas);

这是由androID源支持的.请注意,SurfaceHolder #lock调用mSurfaceLock.lock().这也在SurfaceHolder#updateWindow中调用,该文件在该文件的各种其他位置调用.

mSurfaceLock是ReentrantLock,文档说明:

The constructor for this class accepts an optional fairness parameter.
When set true, under contention, locks favor granting access to the
longest-waiting thread. Otherwise this lock does not guarantee any
particular access order.

SurfaceVIEw没有指定公平性,因此它应该使用默认值,这可能导致这种饥饿.

尝试移动您的一些工作,特别是锁定/解锁呼叫之外的睡眠.

总结

以上是内存溢出为你收集整理的android – 为什么SurfaceView的onTouchEvent被叫几秒延迟?全部内容,希望文章能够帮你解决android – 为什么SurfaceView的onTouchEvent被叫几秒延迟?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1107573.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存