Android中如何在延迟后调用方法
我希望能够在指定的延迟后调用以下方法。 在 Objective C 中,有类似这样的内容:
[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];
在 android 和 java 中是否有与此方法等效的方法? 例如,我需要能够在 5 秒后调用一个方法。
public void DoSomething()
{
//do something here
}
I want to be able to call the following method after a specified delay.
In objective c there was something like:
[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];
Is there an equivalent of this method in android with java?
For example I need to be able to call a method after 5 seconds.
public void DoSomething()
{
//do something here
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
Kotlin
Java
要导入的类是
android.os.handler
。Kotlin
Java
The class to import is
android.os.handler
.我无法在我的案例中使用任何其他答案。
我使用了原生的 java Timer 来代替。
I couldn't use any of the other answers in my case.
I used the native java Timer instead.
注意:当问题未指定 Android 作为上下文时给出此答案。对于特定于 Android UI 线程的答案查看此处。
看起来 Mac OS API 让当前线程继续,并且安排任务异步运行。在 Java 中,
java.util.concurrent
包提供了等效的功能。我不确定 Android 可能会施加哪些限制。Note: This answer was given when the question didn't specify Android as the context. For an answer specific to the Android UI thread look here.
It looks like the Mac OS API lets the current thread continue, and schedules the task to run asynchronously. In the Java, the equivalent function is provided by the
java.util.concurrent
package. I'm not sure what limitations Android might impose.5 秒后在 UI 线程中执行某些操作:
For executing something in the UI Thread after 5 seconds:
1. 使用
Handler
2. 使用 TimerTask
甚至更短
或最短的是
3. 使用
Executors
1. 使用
Handler
2. 使用
Timer
3. 使用
ScheduledExecutorService
1. Using
Handler
2. Using TimerTask
Or even shorter
Or shortest would be
3. Using
Executors
1. Using
Handler
2. Using
Timer
3. Using
ScheduledExecutorService
您可以在 UIThread 中使用 Handler:
you can use Handler inside UIThread:
感谢所有精彩的答案,我找到了最适合我的需求的解决方案。
Thanks for all the great answers, I found a solution that best suits my needs.
更多安全性 - 使用 Kotlin 协程
大多数答案都使用 Handler,但我提供了一种不同的解决方案来使用 Android 生命周期扩展来处理活动、片段和视图模型中的延迟。 此方法会在生命周期销毁时自动取消,避免内存泄漏或应用崩溃
在 Activity 或 Fragment 中:
在 ViewModel 中:
在挂起函数:(Kotlin 协程)
如果您收到 lifecycleScope not find! 的错误! - 将此依赖项导入到应用程序 gradle 文件中:
More Safety - With Kotlin Coroutine
Most of the answers use Handler, but I provide a different solution to handle delays in activity, fragment, and view model using Android Lifecycle extensions. This approach will automatically cancel when the lifecycle is destroyed, avoiding memory leaks or app crashes
In Activity or Fragment:
In ViewModel:
In suspend function: (Kotlin Coroutine)
If you get an error with the lifecycleScope not found! - import this dependency to the app gradle file:
看这个演示:
See this demo:
如果您必须使用 Handler,但您进入了另一个线程,则可以使用
runonuithread
在 UI 线程中运行该处理程序。这将使您免于抛出要求调用 Looper.Prepare() 的异常看起来很混乱,但这是方法之一。
If you have to use the Handler, but you are into another thread, you can use
runonuithread
to run the handler in UI thread. This will save you from Exceptions thrown asking to callLooper.Prepare()
Looks quite messy, but this is one of the way.
我更喜欢使用 View.postDelayed() 方法,简单代码如下:
I prefer to use
View.postDelayed()
method, simple code below:这是我的最短解决方案:
Here is my shortest solution:
如果您使用的是 Android Studio 3.0 及更高版本,则可以使用 lambda 表达式。方法
callMyMethod()
在 2 秒后调用:如果您需要取消延迟的可运行,请使用以下命令:
If you are using Android Studio 3.0 and above you can use lambda expressions. The method
callMyMethod()
is called after 2 seconds:In case you need to cancel the delayed runnable use this:
我建议 计时器,它允许您安排一个在非常特定的时间间隔调用的方法。这不会阻塞您的 UI,并在执行该方法时使您的应用程序保持响应。
另一个选项是 wait(); 方法,这将阻塞当前线程指定的时间长度。如果您在 UI 线程上执行此操作,这将导致您的 UI 停止响应。
I suggest the Timer, it allows you to schedule a method to be called on a very specific interval. This will not block your UI, and keep your app resonsive while the method is being executed.
The other option, is the wait(); method, this will block the current thread for the specified length of time. This will cause your UI to stop responding if you do this on the UI thread.
因此,这里需要考虑一些事情,因为给这只猫剥皮的方法有很多。虽然答案都已经给出了选择和选择。我认为重要的是,用适当的编码指南重新审视这一点,以避免任何人仅仅因为“大多数选择的简单答案”而走上错误的方向。
因此,首先让我们讨论简单的延迟后答案,这是该线程中总体获胜者选择的答案。
有几点需要考虑。延迟后,您可能会遇到内存泄漏、死对象、生命周期消失等问题。所以正确处理它也很重要。您可以通过几种方式来做到这一点。
为了现代开发,我将在 KOTLIN 中提供
这里是一个在回调上使用 UI 线程的简单示例,并在您点击回调时确认您的活动仍然有效。
但是,这仍然不完美,因为如果活动消失,就没有理由触发回调。所以更好的方法是保留对它的引用并像这样删除它的回调。
当然,在 onPause 上处理清理,这样它就不会触发回调。
现在我们已经讨论了显而易见的事情,让我们来谈谈现代协程和 kotlin 的更简洁的选择:)。如果你还没有使用这些,那你就真的错过了。
或者,如果您想始终在该方法上执行 UI 启动,您可以简单地执行以下操作:
当然,就像 PostDelayed 一样,您必须确保处理取消,以便您可以在延迟调用后进行活动检查,也可以在onPause 就像其他路线一样。
//handle cleanup
如果将 launch(UI) 放入方法签名中,则可以在调用代码行中分配作业。
因此,这个故事的寓意是要确保延迟操作的安全,确保删除回调或取消工作,当然还要确认您有正确的生命周期来完成延迟回调上的项目。协程还提供可取消的操作。
另外值得注意的是,您通常应该处理协程可能带来的各种异常。例如,取消、异常、超时,无论您决定使用什么。如果您决定真正开始使用协程,这里有一个更高级的示例。
So there are a few things to consider here as there are so many ways to skin this cat. Although answers have all already been given selected and chosen. I think it's important that this gets revisited with proper coding guidelines to avoid anyone going the wrong direction just because of "majority selected simple answer".
So first let's discuss the simple Post Delayed answer that is the winner selected answer overall in this thread.
A couple of things to consider. After the post delay, you can encounter memory leaks, dead objects, life cycles that have gone away, and more. So handling it properly is important as well. You can do this in a couple of ways.
For sake of modern development, I'll supply in KOTLIN
Here is a simple example of using the UI thread on a callback and confirming that your activity is still alive and well when you hit your callback.
However, this is still not perfect as there is no reason to hit your callback if the activity has gone away. so a better way would be to keep a reference to it and remove it's callbacks like this.
and of course handle cleanup on the onPause so it doesn't hit the callback.
Now that we have talked through the obvious, let's talk about a cleaner option with modern day coroutines and kotlin :). If you aren't using these yet, you are really missing out.
or if you want to always do a UI launch on that method you can simply do:
Of course just like the PostDelayed you have to make sure you handle canceling so you can either do the activity checks after the delay call or you can cancel it in the onPause just like the other route.
//handle cleanup
If you put the launch(UI) into the method signature the job can be assigned in the calling line of code.
so moral of the story is to be safe with your delayed actions, make sure you remove your callbacks, or cancel your jobs and of course confirm you have the right life cycle to touch items on your delay callback complete. The Coroutines also offers cancelable actions.
Also worth noting that you should typically handle the various exceptions that can come with coroutines. For example, a cancelation, an exception, a timeout, whatever you decide to use. Here is a more advanced example if you decide to really start utilizing coroutines.
对于简单的线路处理后延迟,您可以执行以下操作:
我希望这有帮助
For a Simple line Handle Post delay, you can do as following :
I hope this helps
您可以将其用于最简单的解决方案:
另外,下面可以是另一个干净有用的解决方案:
You can use this for Simplest Solution:
Else, Below can be another clean useful solution:
您可以使用新引入的 lambda 表达式使其更加简洁:
You can make it much cleaner by using the newly introduced lambda expressions:
使用 Kotlin,我们可以通过执行以下操作来实现
Using Kotlin, we can achieve by doing the following
如果您使用 RxAndroid,那么线程和错误处理就会变得更加容易。以下代码在延迟后执行
If you use RxAndroid then thread and error handling becomes much easier. Following code executes after a delay
我创建了更简单的方法来调用它。
要使用它,只需调用:
.CallWithDelay(5000, this, "DoSomething");
I created simpler method to call this.
To use it, just call :
.CallWithDelay(5000, this, "DoSomething");
当你得到下面的一个作品时,
Below one works when you get,
使用
CountDownTimer
非常简单。有关更多详细信息 https://developer.android.com/reference/android/os /CountDownTimer.html
It's very easy using the
CountDownTimer
.For more details https://developer.android.com/reference/android/os/CountDownTimer.html
我喜欢干净的东西:
这是我的实现,在您的方法中使用的内联代码
I like things cleaner:
Here is my implementation, inline code to use inside your method
runOnUiThread :
example:
每个人似乎都忘记在发布新的可运行程序或消息之前清理处理程序。否则它们可能会累积并导致不良行为。
everybody seems to forget to clean the Handler before posting a new runnable or message on it. Otherway they could potentially accumulate and cause bad behaviour.
这是另一个棘手的方法:当可运行对象更改 UI 元素时,它不会抛出异常。
您可以这样调用动画:
动画可以附加到任何视图。
Here is another tricky way: it won't throw exception when the runnable change UI elements.
You can call the animation like this:
Animation can attach to any view.
这是 Kotlin 中的答案,你们这些懒惰的人:
Here is the answer in Kotlin you lazy, lazy people:
Activity/Fragment - 在这种情况下如果您对UI进行了更改,那么您应该使用viewLifecycleOwner的lifecycleScope因为在销毁 Activity/Fragment 的情况下,此操作将是安全的并且不会执行,否则如果没有 viewLifecycleOwner,应用程序将在修改未绑定到任何内容的 UI 时崩溃。
Activity/Fragment - in this case if you doSomething with UI changes, then you should use viewLifecycleOwner's lifecycleScope because in the case of destroying the Activity/Fragment this operation is going to be safe and is not to execute, otherwise without viewLifecycleOwner the app will crash when modifying the UI that would be not bound to anything.