我希望能够在指定的延迟后调用以下方法。 在objective c中,有这样的东西:

[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];

在android和java中是否有类似的方法? 例如,我需要能够在5秒后调用一个方法。

public void DoSomething()
{
     //do something here
}

当前回答

你可以使用新引入的lambda表达式让它更简洁:

new Handler().postDelayed(() -> {/*your code here*/}, time);

其他回答

如果你使用Android Studio 3.0及以上版本,你可以使用lambda表达式。callMyMethod()方法在2秒后被调用:

new Handler().postDelayed(() -> callMyMethod(), 2000);

如果你需要取消延迟的可运行文件,请使用以下命令:

Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);

// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);

对于简单行句柄Post延迟,您可以执行以下操作:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do someting
    }
}, 3000);

我希望这对你们有帮助

谢谢你的回答,我找到了一个最适合我需要的解决方案。

Handler myHandler = new DoSomething();
Message m = new Message();
m.obj = c;//passing a parameter here
myHandler.sendMessageDelayed(m, 1000);

class DoSomething extends Handler {
    @Override
    public void handleMessage(Message msg) {
      MyObject o = (MyObject) msg.obj;
      //do something here
    }
}

我更喜欢使用View.postDelayed()方法,下面是简单的代码:

mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 1000 ms
    }
}, 1000);

所以这里有几件事要考虑,因为有这么多方法来剥这只猫的皮。尽管答案都已经给出了。我认为重要的是,要用适当的编码指南重新审视这个问题,以避免任何人仅仅因为“多数选择的简单答案”而走向错误的方向。

因此,首先让我们讨论一下简单的Post Delayed answer,这是在这个线程中胜出的答案。

有几件事需要考虑。在post延迟之后,您可能会遇到内存泄漏、死对象、生命周期消失等等。所以正确处理也很重要。有几种方法可以做到这一点。

为了现代发展,我将在KOTLIN供应

下面是一个简单的例子,在回调中使用UI线程,并在你点击回调时确认你的活动仍然活跃。

  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()
  }

当然,就像PostDelayed一样,你必须确保你处理取消,所以你可以在延迟调用后做活动检查,或者你可以像其他路由一样在onPause中取消它。

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

如果您将启动(UI)放入方法签名中,作业可以在调用代码行中分配。

这个故事的寓意是要保证延迟操作的安全性,确保你删除了你的回调,或者取消了你的作业当然还要确认你有正确的生命周期去触摸你的延迟回调完成上的项。协程还提供了可取消的操作。

同样值得注意的是,您通常应该处理协程带来的各种异常。例如,取消、异常、超时,无论您决定使用什么。下面是一个更高级的示例,如果您决定真正开始使用协同程序。

   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}")
            }
        }