Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android lockCanvas方法在游戏循环中偶尔出现口吃/延迟_Android_Android Canvas_Game Loop_Surfaceholder - Fatal编程技术网

Android lockCanvas方法在游戏循环中偶尔出现口吃/延迟

Android lockCanvas方法在游戏循环中偶尔出现口吃/延迟,android,android-canvas,game-loop,surfaceholder,Android,Android Canvas,Game Loop,Surfaceholder,我以给定的速度平滑滚动位图。我用一个游戏循环来做这件事。 除了偶尔的口吃/跳跃外,它的滚动速度非常平稳,大约每秒60帧。这些跳跃发生在任何地方,从每秒一次到每秒几次。通常,跑步几秒钟后,它们开始或变得更频繁,但我不确定这是否是一个重要线索 跳转的原因是,有时运行循环的迭代将花费通常的两倍时间,因此位图将在一个位置停留一段时间,然后进一步跳转以赶上并保持其恒定速度。我使用插值计算位图的新位置,每次更新都基于经过的时间。当一段比平时更长的时间过去后,我尝试了几次小更新,而不是一次移动整个距离,但是暂

我以给定的速度平滑滚动位图。我用一个游戏循环来做这件事。 除了偶尔的口吃/跳跃外,它的滚动速度非常平稳,大约每秒60帧。这些跳跃发生在任何地方,从每秒一次到每秒几次。通常,跑步几秒钟后,它们开始或变得更频繁,但我不确定这是否是一个重要线索

跳转的原因是,有时运行循环的迭代将花费通常的两倍时间,因此位图将在一个位置停留一段时间,然后进一步跳转以赶上并保持其恒定速度。我使用插值计算位图的新位置,每次更新都基于经过的时间。当一段比平时更长的时间过去后,我尝试了几次小更新,而不是一次移动整个距离,但是暂停的位图仍然非常明显

我运行了traceview,额外的时间都花在了lockCanvas中。大多数情况下,这种方法大约需要10毫秒,但在这种长时间的情况下,大约需要24毫秒。当我追踪4秒钟时,这发生了7次

在下面的代码中,如果它运行得很快,我会让它休眠一段时间,但这实际上没有任何区别。如果我去掉了那部分代码,我的问题就没有解决。不需要恒定的帧速率,因为我只是根据经过的时间计算位置

@Override
    public void run() {


         long beginTime = 0;     // 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)
         sleepTime = 0;
        while (mRun) {
            Canvas c = null;

            try {
                beginTime = System.currentTimeMillis();

                c = mSurfaceHolder.lockCanvas(null);
                synchronized (mSurfaceHolder) {

                    if (mMode == STATE_RUNNING) {
                        updatePhysics();
                    }
                    doDraw(c);
                }


            } catch(Exception e){
                System.out.println(e.getStackTrace());
            }finally {

                if (c != null) {
                    mSurfaceHolder.unlockCanvasAndPost(c);
                }
            }
            timeDiff = System.currentTimeMillis() - beginTime;

            sleepTime = (int)(FRAME_PERIOD - timeDiff);

            if(sleepTime > 0){

                 try {
                    Thread.sleep(sleepTime);
                 } catch (InterruptedException e) {}
            }
        }
    }
@覆盖
公开募捐{
long beginTime=0;//循环开始的时间
long-timeDiff;//循环执行所用的时间

int sleepTime;//ms to sleep(一种可能的解释是,您的代码会生成许多短期对象,垃圾收集器会定期启动以回收内存

这些明显的停顿是Java早期版本开发人员的祸根,直到分代垃圾收集基本上消除了这个问题。然而,据我所知,Android的Dalvik虚拟机不采用分代垃圾收集,因此在创建立即丢弃的对象时应谨慎,尤其是在循环中结盟

分析内存分配将更清楚地说明这个问题


如果这确实是问题所在,您可以尝试重用对象,或使用原语处理数据。

一种可能的解释是,您的代码生成了大量短期对象,垃圾收集器会定期启动以回收内存

这些明显的停顿是Java早期版本开发人员的祸根,直到分代垃圾收集基本上消除了这个问题。然而,据我所知,Android的Dalvik虚拟机不采用分代垃圾收集,因此在创建立即丢弃的对象时应谨慎,尤其是在循环中结盟

分析内存分配将更清楚地说明这个问题

如果这确实是问题所在,您可以尝试重用对象,或者使用原语处理数据。

FWIW,这里有类似的问题:。现在“systrace”在计算时间花费在哪里方面非常有效,尽管您需要一个根设备来获取一些信息。FWIW,这里有类似的问题:。现在的“systrace”虽然你需要一个根设备来获取一些info.FWIW,但姜饼附带了一个“大部分并发”垃圾收集器,大大减少了暂停时间。但是,最好的暂停是不暂停。在最近的版本中,你可以添加“dalvik”查看systrace标记列表以查看跟踪输出中的GC暂停;如果它们是问题所在,则很容易看出。如果没有其他问题,则GC会在logcat中记录,因此可以将暂停与log output.FWIW关联起来,这是一种“主要并发的”垃圾收集器附带姜饼,显著减少了暂停时间。但是,最好的暂停是不暂停。在最近的版本中,您可以添加“dalvik”查看systrace标记列表,查看跟踪输出中的GC暂停;如果是问题,则很容易看出。如果没有其他问题,则GC会在logcat中记录,因此可以将暂停与日志输出关联起来。