我希望能在指定的延迟时间后调用下面的方法。 在Objective-C中,有一个类似于以下代码的方法:
[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];
在安卓Java中是否有此方法的等效方法?例如,我需要在5秒后调用一个方法。
public void DoSomething()
{
//do something here
}
我更喜欢使用 View.postDelayed()
方法,下面是简单的代码:
mView.postDelayed(new Runnable() {
@Override
public void run() {
// Do something after 1000 ms
}
}, 1000);
以下是我最简洁的解决方案:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
callMyMethod()
将在2秒后被调用。new Handler().postDelayed(() -> callMyMethod(), 2000);
如果你需要取消延迟的 runnable,请使用以下代码:
Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);
// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//DO SOME ACTIONS HERE , THIS ACTIONS WILL WILL EXECUTE AFTER 5 SECONDS...
}
});
}
}, 5000);
那么在这里有几件事情需要考虑,因为有很多方法可以解决这个问题。尽管答案已经被选择和确定,但我认为重新审视这个问题并遵守适当的编码规范很重要,以避免因“大多数选择简单答案”而导致任何人走错方向。
首先让我们讨论简单的Post Delayed答案,这是整个主题中选择的获胜者。
有几件事情需要考虑。在延迟发布后,您可能会遇到内存泄漏、死对象、生命周期已过期等问题,因此正确处理很重要。您可以通过以下几种方式来做到这一点。
为了现代开发,请使用KOTLIN
这里是一个简单的示例,使用UI线程进行回调,并在触发回调时确认您的activity仍然存在且正常工作。
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
然而,这仍然不完美,因为如果活动已经消失,没有理由触发回调。所以更好的方法是保留对它的引用并像这样移除它的回调。
private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.VISIBLE
mHandler.postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
}
}
当然,在onPause中处理清理工作,以防止它击中回调函数。
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
现在我们已经讨论了显而易见的内容,让我们谈谈使用现代协程和Kotlin的更清晰的选项:)。如果您还没有使用这些,则真的错过了很多。
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
如果你想在该方法上始终执行UI启动,那么你可以简单地执行以下操作:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
var mDelayedJob: Job? = null
fun doActionAfterDelay()
mDelayedJob = launch(UI) {
try {
delay(MS_TO_DELAY)
actionToTake()
}catch(ex: JobCancellationException){
showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
}
}
}
}
//处理清理
override fun onPause() {
super.onPause()
if(mDelayedJob != null && mDelayedJob!!.isActive) {
A35Log.v(mClassTag, "canceling delayed job")
mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
}
}
mLoadJob = launch(UI){
try {
//Applies timeout
withTimeout(4000) {
//Moves to background thread
withContext(DefaultDispatcher) {
mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
}
}
//Continues after async with context above
showFancyToast("Loading complete", true, FancyToast.SUCCESS)
}catch(ex: JobCancellationException){
showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
}catch (ex: TimeoutCancellationException) {
showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
}catch(ex: Exception){
showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
}
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Do someting
}
}, 3000);
您可以尝试以下方法来解决问题:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Write your code here
}
}, 5000); //Timer is in ms here.
new Handler().postDelayed(() ->
{/*Do something here*/},
5000); //time in ms
通过使用新引入的lambda表达式,您可以使代码更加简洁:
new Handler().postDelayed(() -> {/*your code here*/}, time);
使用Kotlin,我们可以通过以下方式实现
Handler().postDelayed({
// do something after 1000ms
}, 1000)