Android 如何让方法暂停并等待输入?

发布于 2024-09-29 06:58:58 字数 427 浏览 0 评论 0原文

基本上,我创建了一个二十一点应用程序,它使用多种被调用的方法并传递大量所需的信息(关于纸牌和操作)。我在屏幕上显示了 2 个可单击的按钮(击中和站立)。现在我有一个称为玩家回合的方法...这是当我(通过静态整数)选择一个按钮时,事情就会发生。然而,我用无限的 while 循环来做到这一点,认为它只会继续检查是否按下了按钮,然后仅在按下按钮时才执行操作。这不起作用,因为每次文本视图或图像视图更改后我的屏幕都不会刷新,因此一旦我点击开始游戏,游戏就会“冻结”(由于该方法永远不会结束),因此我无法单击所述按钮。有没有一种方法可以在android中调用类似于java中的键盘监听器(它暂停活动并等待用户输入)的东西?如果没有,您建议的解决方法是什么?最后(虽然目前并不重要)我如何在每次更改后正确刷新所有内容(我相信我需要使用 invalidate.. 虽然我不确定在 invalidate 之前有什么,所以它会刷新整个内容)?提前谢谢大家。

Basically I have created a Blackjack app that uses several methods that get called and pass a long the information that is needed (about cards and actions). I have 2 buttons displayed on screen that are click able (hit and stand). Now I have a method called player turn... and this is when I (through static ints) have if a button is selected, things will happen. However I did this with an infinite while loop thinking it will just keep checking to see if a button is pressed and then only do action when a button is pressed. This isn't working as my screen is not refreshing after each textview or imageview change thus as soon as I hit start game the game appears to "freeze" (being due to the method never ending) and I am therefore unable to click said buttons. Is there a way to call something similar to keyboard listener in java (Which pauses activity and waits for user input), in android? If not, what would you suggest the workaround be? Lastly (though not as currently important) how would I properly refresh everything after each change (I believe I need to use invalidate.. though I'm not sure what to have before invalidate so it refreshes the whole thing)? Thanks a bunch in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

撧情箌佬 2024-10-06 06:58:58

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

看一下下面的设计片段:

activity actions

假设您愿意“睡觉”的方法是 <来自 MainActivity 类的 code>doSomething 。我假设这是从某些事件处理程序实现中调用的。您应该将该方法的所有调用移至 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 修改,并且还可以监听用户事件。

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

Looks like a new Activity (invoked by startActivityForResult), and a Handler (called from the onActivityResult) could solve your problem.

Take a look at the design-snippet bellow:

activity interactions

Let's say the method you are willing to 'sleep' is the doSomething from the MainActivity class. I assume this is invoked from some event handler implementation. You should move all the calls from that method into the BackgroundActivity activity,
- which should show a ProgressDialog and/or nothing else -.
In your doSomething method you should start an activity by an intent pointing to the BackgroundActivity with

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

where BG_ACTIVITY_ID is your unique identifier for the started activity, so when it finishes, you can handle it.

Inside the processBackgroundData (or when the background activity is finished processing), you should set the result before calling finish():

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

In your MainActivity you should also override the onActivityResult method, to retrieve the necessary information from the finished BackgroundActivity task:

@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;
    }
}

And inside your BackgroundHandler's handleMessage method (since you are back to the ui thread: the thread in which your main application is running) you can do all the necessary ui modifications, and also listen forward for the user events.

This way you are getting rid of the infinite loop, and can always be aware of user interactions.

女皇必胜 2024-10-06 06:58:58

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

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

我最近想出了一个主意,但我对 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 等待我的输入。

这是一个好的技术吗?

是否存在我尚未发现的问题?

一直以来大家都是这样做的吗
只有像我这样的新手才认为他们在做某事?

The Activity Callback Routines WAIT for the last Event Listener...
Could this be an Easy Solution??

This "wait for user input" question is a question that comes up regularly, has puzzled me as well, and I haven't as yet seen what looks to me like a real clean solution.

I came up with an idea, recently, but I'm pretty green at the Android game and I want to see how it holds up to scrutiny.

The technique is based on the idea that the activity callback routines do not complete as long as there is an event listener that continues to listen. As a result, the callback routine executes the last statement, and then does nothing but does not end. (IOW, "you can check out any time you want, but you can never leave....until the event listeners let you." Yuk.)

This seems to fit the requirements. The UI is not frozen and there is no infinite loop. The only demand on the UI is that it sustain the event listner. When the user supplies the input, the event callback routine, i.e. onKey, handles the input, and then does ALL THE STEPS REQUIRED BEFORE THE NEXT user input is needed. Then the event callback routine sets a new listener and returns, releasing the old listener, and leaving the UI with one task -- sustain the new listener. This continues iteratively until the activity callback routine is completed.

Here is some code I tested:

@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;    
}

The foregoing code seems to do what is required...onStart waited for my input.

Is this a good technique?

Are there problems I haven't identified?

Has everybody been doing this all along,
and only newbies like myself think they are on to something?

踏雪无痕 2024-10-06 06:58:58

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

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

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

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

如果您可以使视图无效,那么Android 事件循环将负责重新绘制屏幕,​​包括任何布局更改。如果您有自定义视图,则将根据需要调用其 onDraw() 。

希望这有帮助。

Android will run an event loop for you - so you don't have to loop around waiting for input yourself.

You can hook into the loop in a number of ways. From 1.6 onwards the easiest way to do this is to specify the hook in your XML, e.g:

<Button android:onClick="myClickHandler" />

Alternatively you can do this in code by calling setOnClickListener.

Take a look at http://android-developers.blogspot.com/2009/10/ui-framework-changes-in-android-16.html for some examples (read the section headed "Easier click listeners")

If you can invalidate on your view then the Android event loop will take care of re-drawing the screen, including any layout changes. If you have custom View's their onDraw() will be called as appropriate.

Hope this helps.

南渊 2024-10-06 06:58:58

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

类似于当您启动键盘时,java 会等待键盘输入。

Hm I might have the wrong interpretation but it seems that doing setOnClickListener has it so that when that certain part of the code is reached, the button becomes clickable and actions are taken when the button is clicked? I already have it so that when a button is clicked and it's Player's turn, actions will occur. However what I need to know is how to have the program literally wait or pause until one of the buttons are pressed.

Similar to when you incite a keyboard and java waits for keyboard input to be made.

你穿错了嫁妆 2024-10-06 06:58:58

不要轮询以查看您的按钮是否已被按下。只需在 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 发布的链接,您会发现有一种不太“type-y”的方法可以做到这一点,即向您的 AndroidManifest 文件添加内容。您只需将其指向类中具有正确签名的函数(我记得 public void funcName(View v)),Android 就会为您处理所有侦听器内容。

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

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

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

Do Not Poll to see if your button has been pressed. Just do whatever it is you want done in the OnClickHandler.

Here's an example of what your code might look like (The Wrong Way):

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

And here's the right way:

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);

  ...
}

Yes, the Right Way involves a bit more typing... but it also works. And if you look at the link Collin posted, there's a less "type-y" way to do it that involves adding stuff to your AndroidManifest file. You just point it at a functions in your class with the right signature (public void funcName(View v) as I recall), and Android handles all the listener stuff for you.

As far as "making your program wait", it already is. Your program code isn't running until some call is made to one of your classes' entry points. Until then, execution is floating around in Android's UI handler code in your process, passing messages to and fro. As soon as one of those messages ends up in your app, (onCreate, a click listener, etc) your code does it's thing and returns, allowing that UI thread to go back to handling all the input for your app's process.

And if your app takes longer than 5 seconds or so to respond to a message, it'll be killed by the system, with an "ANR"... App Not Responding.

Another handy Google IO video entitled "Writing Zippy Android Apps".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文