Kotlin - 如何将一个Runnable作为this传递给Handler

10

我是kotlin的初学者。我尝试创建一个每2秒重复一次的任务。所以我创建了这样的东西。

val handler = Handler()
    handler.postDelayed(Runnable {
        // TODO - Here is my logic

        // Repeat again after 2 seconds
        handler.postDelayed(this, 2000)
    }, 2000)

但是在postDelayed(this)中,它会给出错误 -需要Runnable!,找到MainActivity。我甚至尝试过this@Runnable ,但它没有起作用。

但是,当我像这样编写相同的函数时,它可以工作

val handler = Handler()
    handler.postDelayed(object : Runnable {
        override fun run() {
            // TODO - Here is my logic

            // Repeat again after 2 seconds
            handler.postDelayed(this, 2000)
        }
    }, 2000)

为什么this关键字在第一个函数中无法工作,但在第二个函数中它能很好地工作呢?

4个回答

6
你可以采取以下几种方法:
  1. make both the runnable and the handler be in the same scope

        //class scope
        val handler = Handler()
        val runnable = object : Runnable {
           override fun run () {
             handler.removeCallbacksAndMessages(null) 
             //make sure you cancel the 
              previous task in case you scheduled one that has not run yet
             //do your thing
    
             handler.postDelayed(runnable,time)
          }
       }
    
然后在某个函数中。
handler.postDelayed(runnable,time)
  1. You can run a timertask, which would be better in this case

     val task = TimerTask {
        override fun run() {
         //do your thing
        }
     }
    
     val timer = Timer()
    
     timer.scheduleAtFixedRate(task,0L, timeBetweenTasks)
    

非常感谢您 :) - Hayk Mkrtchyan
但是第一段代码对我不起作用。它没有覆盖运行方法。 - Hayk Mkrtchyan
在第一种情况下,您仍然需要 val runnable = object : Runnable { ... } - Alexey Romanov

3
第一个函数接受一个lambda表达式并返回一个Runnable对象。在这种情况下,this没有任何意义。
第二个函数定义了一个实现Runnable接口的匿名对象。在这种情况下,this指代该对象实例本身。

非常感谢您的支持 :) - Hayk Mkrtchyan
@m0skit0,当您说“第一个”时,是指OP的第一个代码示例中的Runnable{...}吗?如果是这样,我能否问一下是否有关于此用法的参考资料?嗯,在Kotlin中,如果参数是lambda,我们可以省略函数的括号,但我认为那不是一个函数,而只是一个lambda,而符号Runnable只是为了避免混淆(我从Kotlin文档中读到的)。如果我理解有误,请告诉我。先感谢您。 - starriet
Runnable 是一个从函数式接口转换为 lambda 的 SAM。它等同于第二个示例,只是语法糖,以避免冗长。 - m0skit0

2
以下示例将有效运行。
val runnable = object : Runnable { 
        override fun run() {
         
            handler.postDelayed(this,1000)
        }
    }

是的,当我们以这种方式创建可运行对象时,我们可以通过此关键字获取对它的引用。但是使用lambda表达式就不可能了)) - Hayk Mkrtchyan

1
在您的情况下,当使用this时,它意味着"本地最终类<未命名>:可运行",指的是一个头部可运行对象。
runnable=object : Runnable {
            override fun run() {
                // i is a counter
                println("No. "+i++)
                // Repeat again after 2 seconds
                handler.postDelayed(this, 2000)
            }
        }
        handler.postDelayed(runnable,0)

runnable 在方法内部使用。由于 Handler() 被弃用,我们必须像这样使用:

var handler: Handler = Handler(Looper.getMainLooper())
var runnable: Runnable = Runnable { }

此外,您可以通过以下方式在任何地方停止此方法:
handler.removeCallbacks(runnable)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接