Android 如何让方法暂停并等待输入?
基本上,我创建了一个二十一点应用程序,它使用多种被调用的方法并传递大量所需的信息(关于纸牌和操作)。我在屏幕上显示了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
看起来一个新的
Activity
(由startActivityForResult
调用)和一个Handler
(从onActivityResult
调用)可以解决你的问题。看一下下面的设计片段:
假设您愿意“睡觉”的方法是 <来自
MainActivity
类的 code>doSomething 。我假设这是从某些事件处理程序实现中调用的。您应该将该方法的所有调用移至BackgroundActivity
活动中,- 应该显示 ProgressDialog 和/或其他任何内容 -。
在 doSomething 方法中,您应该通过指向 BackgroundActivity 的意图来启动一个活动,其中
BG_ACTIVITY_ID 是已启动活动的唯一标识符,因此当它完成时,您可以处理它。
在 processBackgroundData 内(或当后台活动完成处理时),您应该在调用 finish() 之前设置结果:
在 MainActivity 中,您还应该重写 onActivityResult 方法,从已完成的BackgroundActivity任务中检索必要的信息:
在您的
BackgroundHandler
的handleMessage
方法中(因为您回到了ui线程:您的主应用程序所在的线程正在运行)您可以进行所有必要的 ui 修改,并且还可以监听用户事件。这样您就可以摆脱无限循环,并且始终可以了解用户交互。
Looks like a new
Activity
(invoked bystartActivityForResult
), and aHandler
(called from theonActivityResult
) could solve your problem.Take a look at the design-snippet bellow:
Let's say the method you are willing to 'sleep' is the
doSomething
from theMainActivity
class. I assume this is invoked from some event handler implementation. You should move all the calls from that method into theBackgroundActivity
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
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():In your MainActivity you should also override the
onActivityResult
method, to retrieve the necessary information from the finished BackgroundActivity task:And inside your
BackgroundHandler
'shandleMessage
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.
活动回调例程等待最后一个事件侦听器...
这是一个简单的解决方案吗?
这个“等待用户输入”问题是一个经常出现的问题,也让我感到困惑,而且我还没有看到我想要的是什么就像一个真正干净的解决方案。
我最近想出了一个主意,但我对 Android 游戏还很陌生,我想看看它如何经得起审查。
该技术基于这样的思想:只要有事件侦听器继续侦听,活动回调例程就不会完成。结果,回调例程执行最后一条语句,然后什么也不做,但没有结束。 (IOW,“你可以随时查看,但你永远不能离开......直到事件侦听器允许你。”Yuk。)
这似乎符合要求。 UI 不会冻结,也不存在无限循环。对 UI 的唯一要求是它支持事件监听器。当用户提供输入时,事件回调例程(即onKey)处理该输入,然后执行在需要下一个用户输入之前所需的所有步骤。然后,事件回调例程设置一个新的侦听器并返回,释放旧的侦听器,并让 UI 完成一项任务 - 维持新的侦听器。此过程迭代地继续,直到活动回调例程完成。
这是我测试的一些代码:
前述代码似乎执行了所需的操作...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:
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?
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.
嗯,我可能有错误的解释,但似乎执行 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.
不要轮询以查看您的按钮是否已被按下。只需在 OnClickHandler 中执行您想要执行的操作即可。
下面是您的代码的示例(错误的方式):
这是正确的方式:
是的,正确的方式涉及更多的输入...但它也有效。如果您查看 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):
And here's the right way:
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".