繁体   English   中英

为什么view.invalidate不能立即重绘我的安卓游戏中的屏幕

[英]Why isn't view.invalidate immediately redrawing the screen in my android game

我正在尝试制作一款安卓游戏。

我有一个扩展活动并处理所有用户输入的游戏类。 然后我有一个missionView类,它扩展了视图,它在屏幕上绘制了关卡。

当用户点击门时我想添加一些动画。

会发生什么:游戏打电话给door.open。 更改状态,以便view.onDraw函数将门打开半开。 游戏调用view.invalidate,它应该重绘屏幕。 然后游戏睡了半秒钟。 然后再次打电话给door.open。 第二次调用该函数时,它会更改状态,以便view.onDraw函数完全打开门。 然后游戏再次调用view.invalidate。

问题是当它进入view.invalidate时它不会重绘屏幕。 如果我在行上设置断点并运行调试器并单击步骤,则不会进入我的view.onDraw函数。 它甚至无法显示它正在执行的代码。

我所拥有的是:门类:

public boolean open()
{
   if (doorState == DoorState.Closed)
   {
       doorState = DoorState.Opening;

       return true;
   }
   else if (doorState == DoorState.Opening)
   {
        doorState = doorState.Open;
        return true;
   }
   else
   {
      return false;
   }
}

游戏类:

if (tile instanceof DoorTile)
{
    DoorTile doorTile = (DoorTile) tile;
    Door door = doorTile.getDoor();

    if (door.isClosed())
    {
        door.open();
        selectedEntity.openDoor();
        view.invalidate();    // This line does not work

        try 
        {
            Thread.sleep(500);
        } 
        catch (InterruptedException e1) 
        {
             // TODO Auto-generated catch block
             e1.printStackTrace();
        }
        door.open();

        // Handled touch event so break switch statement
        break;
     }
}

View#invalidate告诉系统在主线程空闲后立即重新绘制(通过onDraw)视图。 也就是说,调用invalidate会在所有其他即时工作完成后重新绘制您的视图。 如果从主线程中调用Game类中的代码并将该线程置于休眠状态,那么您不仅仅是暂停渲染,而是将所有输入处理暂停(通常是一个坏主意)。 根据经验,除非你知道自己在做什么,否则永远不要睡觉你没有自己产生的线程。

如果您希望使用Thread#sleep定期延迟游戏逻辑,则在单独的线程中运行它并使用view.postInvalidate()来指示主线程唤醒并调用onDraw。

对于游戏,我实际上会使用较低级别的图形访问。 谷歌的LunarLander就是一个很好的例子。 基本上你需要做两件事:

  • 而不是View使用SurfaceView
  • 从SurfaceView获取处理程序
  • 使用包含的自定义方法repaint()替换view.invalidate()

     private void repaint() { Canvas c = null; try { c = surfaceHolder.lockCanvas(); paint(c); } finally { if (c != null) { surfaceHolder.unlockCanvasAndPost(c); } } } 

Paint方法将包含View.onDraw中的内容

我在申请中遇到了同样的问题。

在我的情况下,我试图从[AsyncTask][2][doInBackground()][1]方法调用invalidate()

通过将invalidate()移动到AsyncTask [onProgressUpdate()][3]方法来解决该问题。 即你无法从AsyncTaskdoInBackground()方法更新UI。 在Android文档中提到它,但它很容易忘记它...所以,不要忘记检查它。

我可能会迟到但我相信这对你有用。

我是用Kotlin做的 您可以根据Java进行修改。

将您的代码放在runOnUIThread()

示例代码:

activity?.runOnUiThread { 
  // Your code goes here
}

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM