2

基本上,我创建了一个 Blackjack 应用程序,该应用程序使用多种方法来调用并传递所需的信息(关于卡片和操作)。我在屏幕上显示了 2 个可点击的按钮(点击和站立)。现在我有一个名为 player turn... 但是,我使用无限循环执行此操作,认为它只会继续检查是否按下按钮,然后仅在按下按钮时执行操作。这不起作用,因为我的屏幕在每次 textview 或 imageview 更改后没有刷新,因此一旦我点击开始游戏,游戏就会出现“冻结”(由于方法永无止境),因此我无法点击所述按钮. 有没有办法在android中调用类似于java中的键盘监听器(暂停活动并等待用户输入)?如果不是,您建议的解决方法是什么?最后(虽然目前不重要)我将如何在每次更改后正确刷新所有内容(我相信我需要使用 invalidate.. 虽然我不确定在 invalidate 之前有什么所以它会刷新整个事情)?提前感谢一堆。

4

5 回答 5

1

活动回调例程等待最后一个事件侦听器......这可能是一个简单的解决方案吗?

这个“等待用户输入”问题是一个经常出现的问题,也让我感到困惑,而且我还没有看到在我看来是一个真正干净的解决方案。

我最近想出了一个主意,但我对 Android 游戏很陌生,我想看看它如何经得起审查。

该技术基于这样一种思想,即只要有一个事件侦听器继续侦听,活动回调例程就不会完成。结果,回调例程执行最后一条语句,然后什么也不做,但没有结束。(IOW,“你可以随时查看,但你永远不能离开......直到事件监听器允许你。”Yuk。)

这似乎符合要求。UI 没有冻结,也没有无限循环。对 UI 的唯一要求是它支持事件侦听器。当用户提供输入时,事件回调例程(即 onKey)会处理输入,然后在需要下一个用户输入之前执行所有必需的步骤。然后事件回调例程设置一个新的侦听器并返回,释放旧的侦听器,并让 UI 完成一项任务——维持新的侦听器。这将迭代地继续,直到活动回调例程完成。

这是我测试的一些代码:

@Override   
    public void onCreate(Bundle savedInstanceState) {       
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main);
    }

         public void onStart() {
           super.onStart();

        final EditText et = (EditText) findViewById(R.id.edittext);
        et.setOnKeyListener(new OnKeyListener() {    
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                    boolean tf = checKey(keyCode, event);
                    if(tf==false)return false;
                    gotPW();
                    return true;
            }
        });
    }


         gotPW(){
               ...do ALL the stuff you want to do before you need more user input
               ...set ANOTHER event listener that is connected to another 
                  event callback method

               ...return, releasing the first event listener, and putting the onStart 
                  routine back in its same state -- nothing to do except to attend to 
                  an event listener.
         }



         //this checks to see if the enter key has been hit
         public boolean checKey(int keyCode, KeyEvent event){   
       if ((event.getAction() == KeyEvent.ACTION_DOWN) && 
                (keyCode == KeyEvent.KEYCODE_ENTER)) 
    {          
        return true;        
    }        
    return false;    
}

上述代码似乎做了需要做的事情……onStart 等待我的输入。

这是一个很好的技术吗?

有没有我没有发现的问题?

是不是每个人一直都在这样做,只有像我这样的新手才认为他们正在做某事?

于 2011-05-08T20:11:01.733 回答
1

看起来像一个新的Activity(由 调用startActivityForResult),而一个Handler(从 调用onActivityResult)可以解决您的问题。

看看下面的设计片段:

活动互动

假设您愿意“睡觉”的方法是doSomething课堂MainActivity上的。我假设这是从某个事件处理程序实现中调用的。您应该将该方法中的所有调用移到BackgroundActivity活动中, - 这应该显示 ProgressDialog 和/或没有其他内容 -。
在你的 doSomething 方法中,你应该通过一个指向 BackgroundActivity 的意图来启动一个活动

this.startActivityForResult(new Intent(this, BackgroundActivity.class), 
    BG_ACTIVITY_ID);

其中 BG_ACTIVITY_ID 是您启动活动的唯一标识符,因此当它完成时,您可以处理它。

在内部processBackgroundData(或当后台活动完成处理时),您应该在调用 finish() 之前设置结果:

final Intent intent = new Intent();
intent.putExtra(KEY_FOR_DATA_YOU_NEED, dataYouNeed);
setResult(Activity.RESULT_OK, intent);
finish();

在您的 MainActivity 中,您还应该覆盖该onActivityResult方法,以从已完成的 BackgroundActivity 任务中检索必要的信息:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    //you might also want to check if the resultCode is `Activity.RESULT_OK`...
    switch (requestCode)
    {
        case BG_ACTIVITY_ID:
            //get the data you need 
            final String dataYouNeed = data.getStringExtra(KEY_FOR_DATA_YOU_NEED);
            //process the data...
            //if necessary (threads!), call your backgroundHandler's 
            //sendMessage with the retrieved informations as obj.parameters
        [...]
            break;
        default:
            [...]
            break;
    }
}

在你BackgroundHandlerhandleMessage方法中(因为你回到了ui线程:你的主应用程序正在运行的线程)你可以做所有必要的ui修改,也可以监听用户事件。

这样您就可以摆脱无限循环,并且始终可以了解用户交互。

于 2011-04-12T11:21:42.803 回答
0

不要轮询以查看您的按钮是否已被按下。只需在 OnClickHandler 中做任何你想做的事情。

这是您的代码可能看起来的示例(错误的方式):

while(1) {
  if (buttonHitClicked()) {
    doHit();
  } else if (buttonStandClicked()) {
    doStand();
  }
  //sleep(); // won't help
}

这是正确的方法:

OnClickListener hitListener = new OnClickListener() {
  public void onClick(View v) { doHit(); }
};
OnClickListener standListener = new OnClickListener() {
  public void onClick(View v) { doStand(); }
};

protected void OnCreate(Bundle savedValues) {
  ...

  Button hitButton = (Button)findViewById(R.id.hitButton);
  button.setOnClickListener(hitListener);

  Button standButton = (Button)findViewById(R.id.standButton);
  button.setOnClickListener(standListener);

  ...
}

是的,正确的方法涉及更多的打字......但它也有效。而且,如果您查看 Collin 发布的链接,则有一种不太“类型-y”的方法,它涉及将内容添加到您的 AndroidManifest 文件中。您只需将它指向您类中具有正确签名的函数(public void funcName(View v)我记得),Android 会为您处理所有侦听器的内容。

至于“让你的程序等待”,它已经是. 在对您的某个类的入口点进行某些调用之前,您的程序代码不会运行。在那之前,执行是在你的进程中的 Android 的 UI 处理程序代码中浮动的,来回传递消息。一旦其中一条消息出现在您的应用程序中,(onCreate、点击侦听器等)您的代码就会执行并返回,从而允许该 UI 线程返回处理应用程序进程的所有输入。

如果您的应用程序响应消息的时间超过 5 秒左右,它将被系统杀死,并显示“ANR”......应用程序无响应。

另一个方便的 Google IO 视频,标题为“编写 Zippy Android 应用程序”。

于 2010-11-02T20:18:57.077 回答
0

Android 将为您运行一个事件循环——因此您不必自己循环等待输入。

您可以通过多种方式连接到循环中。从 1.6 开始,最简单的方法是在 XML 中指定钩子,例如:

<Button android:onClick="myClickHandler" />

或者,您可以通过调用 setOnClickListener 在代码中执行此操作。

查看http://android-developers.blogspot.com/2009/10/ui-framework-changes-in-android-16.html获取一些示例(阅读标题为“更轻松的点击侦听器”的部分)

如果您可以使视图无效,那么 Android 事件循环将负责重新绘制屏幕,​​包括任何布局更改。如果您有自定义视图,他们的 onDraw() 将被适当地调用。

希望这可以帮助。

于 2010-10-26T14:35:02.253 回答
0

嗯,我可能有错误的解释,但似乎做 setOnClickListener 有它,所以当到达代码的特定部分时,按钮变为可点击并在点击按钮时采取行动?我已经有了它,这样当点击一个按钮并且轮到玩家时,就会发生动作。但是,我需要知道的是如何让程序真正等待或暂停,直到按下其中一个按钮。

类似于当您触发键盘并且 java 等待键盘输入时。

于 2010-10-26T15:54:04.537 回答