【问题标题】:What will happen if I use try catch and finally for handler using runnable?如果我使用 try catch 和 finally 使用 runnable 的处理程序会发生什么?
【发布时间】:2016-06-22 03:09:03
【问题描述】:

我使用下面的代码在某个时间间隔后每次完成一些工作,并在“finally”子句中使用后期延迟和可运行的淘汰。这是代码。

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                // do somthing
            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                handler.postDelayed(this, 60000);
            }
        }
    };
    handler.postDelayed(runnable, 60000); 

handler.postDelayed(runnable, 60000); 将运行两次或一次。

【问题讨论】:

    标签: android android-service android-handler


    【解决方案1】:

    视情况而定!

    • 第一件事

    每个 try / catch / finally 块如何正常或突然完成?

    finally 块“总是^”在 try 块退出时执行

    这样可以确保即使发生意外异常也会执行 finally 块。

    ^ 上面的异常 - 如果 jvm 退出或线程被杀死,finally 可能不会执行

    详情见java规范:
    https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2

    • 第二件事

    Handler post/postDelayed 方法执行会如何通过?或失败?出于某种原因 - 如果消息未放入消息队列,则可能会发生这种情况 - 失败时,通常是因为处理消息队列的循环器正在退出。

    但您的语句很可能会产生无限循环

    ** 附注。您需要在 try 块中抛出异常或删除 catch 块(如 try{} finally{} )可以“没有”catch 存在,但 catch 块中的代码没有引发任何异常会使编译器抱怨(代码不会编译)

    如果你想循环 n-times+1 你需要在 Runnable run() 方法的 postDelayed 之前添加一些条件

    在您的情况下代码流执行:

    1. 在runnable定义之外的最后一行的postDelayed方法
    2. runnable 的执行者:
      • 开始尝试块
      • 有或没有传球
      • 通过 finally 块在可运行的 run() 方法中使用 postDelayed - 它将可运行在消息队列中以延迟主线程上的执行
    3. 然后在 2 上无限循环

    所以我应该删除 run() 方法的最后一个 postDelay 以实现 postDelay 只在一个循环中运行。 – AndroidMob

    你可以这样写:

        final Handler handler = new Handler();
        handler.post(new Runnable() {
    
            // this int will also be passed to method post delayed 
            // as "this" keyword applies to Anonymous Class 
            // which body contains everything between brackets of new Runnable() { ... }
            int withThis = 1;
    
            @Override
            public void run() {
                handler.postDelayed(this,1000);
            }
        });
    

    那么我应该在哪里调用方法来完成某件事?在 run() 方法中..? – AndroidMob

    这也取决于您想要实现的目标

    例子

        handler.post(new Runnable() {
    
            int counter = 0;
    
            @Override
            public void run() {
    
                boolean wasPlacedInQue = false;
    
                doPreMethod();
    
                if(counter =< 10) { 
                      doMethod();
                      wasPlacedInQue = handler.postDelayed(this,1000);
                }
    
                if(wasPlacedInQue) { 
                      counter++; 
                      doPostyMethod(); 
                } else doFailureMethod();
    
            }
    

    run() 方法中的代码在所谓的 UI 线程上同步执行 - 它是执行应用程序的主线程,请参阅:

    https://developer.android.com/training/multiple-threads/communicate-ui.html

    如果您有兴趣进一步研究它,我已经为您制作了一个完整的工作示例:

    https://gist.github.com/c3ph3us/7d237d540e60597369856cb1fa652a23

    【讨论】:

    • 所以我应该删除 run() 方法的最后一个 postDelay out 侧以实现 postDelay 仅在一个循环中运行。
    • 是的,我想用...无限循环运行它
    • 那么我应该在哪里调用方法来完成某件事?在 run() 方法中..?
    • handler.post(new Runnable() { @Override public void run() { mymethod(); handler.postDelayed(this,30000); } });
    • @AndroidMob - 查看我的编辑,如果您接受答案并在答案满足您的问题时投票(我的答案的左上角)
    【解决方案2】:

    它肯定会运行两次。因为它们是两个不同的消息,handler 会分别处理它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 2014-11-21
      • 1970-01-01
      • 2018-10-24
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多