我希望能够在指定的延迟后调用以下方法。 在目标c中有类似的东西:
[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];
在android中有与java相同的方法吗? 例如,我需要能够在5秒后调用一个方法。
public void DoSomething()
{
//do something here
}
答案 0 :(得分:1651)
Handler().postDelayed({
//Do something after 100ms
}, 100)
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
答案 1 :(得分:291)
在我的案例中,我无法使用任何其他答案。 我使用了原生的Java Timer。
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// this code will be executed after 2 seconds
}
}, 2000);
答案 2 :(得分:180)
注意:当问题未指定Android作为上下文时,会给出此答案。有关Android UI线程look here.
的特定答案看起来Mac OS API允许当前线程继续,并安排任务以异步方式运行。在Java中,等效函数由java.util.concurrent
包提供。我不确定Android可能会施加什么限制。
private static final ScheduledExecutorService worker =
Executors.newSingleThreadScheduledExecutor();
void someMethod() {
⋮
Runnable task = new Runnable() {
public void run() {
/* Do something… */
}
};
worker.schedule(task, 5, TimeUnit.SECONDS);
⋮
}
答案 3 :(得分:95)
用于在5秒后在UI线程中执行某些操作:
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
//Do something here
}
}, 5000);
答案 4 :(得分:38)
你可以在UIThread中使用Handler:
runOnUiThread(new Runnable() {
@Override
public void run() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//add your code here
}
}, 1000);
}
});
答案 5 :(得分:36)
感谢所有出色的答案,我找到了最适合我需求的解决方案。
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
}
}
答案 6 :(得分:21)
参见此演示:
import java.util.Timer;
import java.util.TimerTask;
class Test {
public static void main( String [] args ) {
int delay = 5000;// in ms
Timer timer = new Timer();
timer.schedule( new TimerTask(){
public void run() {
System.out.println("Wait, what..:");
}
}, delay);
System.out.println("Would it run?");
}
}
答案 7 :(得分:21)
如果必须使用Handler,但是您正在使用另一个线程,则可以使用runonuithread
在UI线程中运行处理程序。这样可以避免因要求调用Looper.Prepare()
runOnUiThread(new Runnable() {
@Override
public void run() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 1 second
}
}, 1000);
}
});
看起来很乱,但这是其中之一。
答案 8 :(得分:16)
我更喜欢使用View.postDelayed()
方法,下面是简单的代码:
mView.postDelayed(new Runnable() {
@Override
public void run() {
// Do something after 1000 ms
}
}, 1000);
答案 9 :(得分:13)
这是我最简短的解决方案:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
答案 10 :(得分:10)
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);
答案 11 :(得分:8)
如果您使用 Android Studio 3.0 及更高版本,则可以使用lambda表达式。方法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);
答案 12 :(得分:7)
大多数答案都使用 Handler,但我给出了一个不同的解决方案来延迟活动、片段、使用 Android Lifecycle ext 的视图模型。这种方式会在生命周期开始销毁时自动取消。
在活动或片段中:
lifecycleScope.launch {
delay(DELAY_MS)
doSomething()
}
在视图模型中:
viewModelScope.lanch {
delay(DELAY_MS)
doSomething()
}
挂起函数:(Kotlin Coroutine)
suspend fun doSomethingAfter(){
delay(DELAY_MS)
doSomething()
}
如果您遇到 lifecycleScope not found 的错误 - 导入到 gradle 文件:
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
答案 13 :(得分:6)
我建议使用Timer,它允许您安排在非常特定的时间间隔内调用的方法。这不会阻止您的UI,并且在执行方法时保持您的应用程序的响应性。
另一个选项是wait();方法,这将阻止当前线程达到指定的时间长度。如果您在UI线程上执行此操作,这将导致UI停止响应。
答案 14 :(得分:6)
Kotlin
和Java
多种方式
Handler
Handler().postDelayed({
TODO("Do something")
}, 2000)
Timer().schedule(object : TimerTask() {
override fun run() {
TODO("Do something")
}
}, 2000)
或更短
Timer().schedule(timerTask {
TODO("Do something")
}, 2000)
或者最短的应该是
Timer().schedule(2000) {
TODO("Do something")
}
Executors
Executors.newSingleThreadScheduledExecutor().schedule({
TODO("Do something")
}, 2, TimeUnit.SECONDS)
在Java中
Handler
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something
}
}, 2000);
Timer
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// Do something
}
}, 2000);
ScheduledExecutorService
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run() {
// Do something
}
};
worker.schedule(runnable, 2, TimeUnit.SECONDS);
答案 15 :(得分:5)
您可以将此用于最简单的解决方案:
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
答案 16 :(得分:4)
使用新引入的lambda表达式可以使它更清晰:
new Handler().postDelayed(() -> {/*your code here*/}, time);
答案 17 :(得分:3)
我创建了更简单的方法来调用它。
public static void CallWithDelay(long miliseconds, final Activity activity, final String methodName)
{
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
Method method = activity.getClass().getMethod(methodName);
method.invoke(activity);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}, miliseconds);
}
要使用它,只需致电:.CallWithDelay(5000, this, "DoSomething");
答案 18 :(得分:3)
当您获得以下作品时,
java.lang.RuntimeException:无法在该线程内部创建处理程序 尚未调用Looper.prepare()
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
答案 19 :(得分:2)
这里有很多事情要考虑,因为有很多方法可以给这只猫换皮。尽管答案已经全部选定。我认为重要的是要重新使用适当的编码准则,以避免任何人仅仅因为“多数人选择了简单答案”而走错了方向。
因此,首先让我们讨论简单的“延迟发布”答案,这是该主题中获胜者整体选择的答案。
需要考虑的几件事。发布延迟之后,您可能会遇到内存泄漏,死对象,已经消失的生命周期等。因此,正确处理它也很重要。您可以通过以下两种方式完成此操作。
为了现代发展,我将在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
}
}
如果将launch(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}")
}
}
答案 20 :(得分:2)
使用CountDownTimer
非常容易。
有关详细信息https://developer.android.com/reference/android/os/CountDownTimer.html
import android.os.CountDownTimer;
// calls onTick every second, finishes after 3 seconds
new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("log", millisUntilFinished / 1000);
}
public void onFinish() {
// called after count down is finished
}
}.start();
答案 21 :(得分:2)
对于简单的行句柄延迟,您可以执行以下操作:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Do someting
}
}, 3000);
我希望这对您有帮助
答案 22 :(得分:1)
每个人似乎忘记在发布新的runnable或消息之前清理Handler。否则,它们可能会累积并导致不良行为。
{{1}}
答案 23 :(得分:1)
Here is the answer在科特林,你是个懒惰的人:
Handler().postDelayed({
//doSomethingHere()
}, 1000)
答案 24 :(得分:1)
我喜欢清洁的东西: 这是我的实现,在您的方法中使用的内联代码
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
答案 25 :(得分:1)
这是另一个棘手的方法:当runnable更改UI元素时,它不会抛出异常。
public class SimpleDelayAnimation extends Animation implements Animation.AnimationListener {
Runnable callBack;
public SimpleDelayAnimation(Runnable runnable, int delayTimeMilli) {
setDuration(delayTimeMilli);
callBack = runnable;
setAnimationListener(this);
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
callBack.run();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
您可以像这样调用动画:
view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));
动画可以附加到任何视图。
答案 26 :(得分:0)
android中的合适解决方案:
private static long SLEEP_TIME = 2 // for 2 second
.
.
MyLauncher launcher = new MyLauncher();
launcher.start();
.
.
private class MyLauncher extends Thread {
@Override
/**
* Sleep for 2 seconds as you can also change SLEEP_TIME 2 to any.
*/
public void run() {
try {
// Sleeping
Thread.sleep(SLEEP_TIME * 1000);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
//do something you want to do
//And your code will be executed after 2 second
}
}
答案 27 :(得分:0)
如果使用RxAndroid,则线程和错误处理将变得更加容易。延迟后执行以下代码
.strip
答案 28 :(得分:0)
类似的解决方案,但使用起来更清洁
将此函数写在类之外
fun delay(duration: Long, `do`: () -> Unit) {
Handler().postDelayed(`do`, duration)
}
用法:
delay(5000) {
//Do your work here
}
答案 29 :(得分:0)
在Android中,我们可以在kotlin下面编写代码,以延迟执行任何功能
class MainActivity : AppCompatActivity() {
private lateinit var handler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
handler= Handler()
handler.postDelayed({
doSomething()
},2000)
}
private fun doSomething() {
Toast.makeText(this,"Hi! I am Toast Message",Toast.LENGTH_SHORT).show()
}
}
答案 30 :(得分:0)
有很多方法可以做到这一点,但最好的方法是使用如下所示的处理程序
long millisecDelay=3000
Handler().postDelayed({
// do your work here
},millisecDelay)
答案 31 :(得分:0)
使用Kotlin,我们可以通过以下操作来实现
Handler().postDelayed({
// do something after 1000ms
}, 1000)