In Android, I often see this as the recommended way to periodically call a function:
Handler handler = new Handler();
private Runnable runnableCode = new Runnable() {
@Override
public void run() {
// Do something here
// Repeat this the same runnable code block again another 2 seconds
handler.postDelayed(runnableCode, 2000);
}
};
handler.post(runnableCode);
I tried to convert this to Kotlin:
val handler = Handler()
val runnableCode = object : Runnable {
override fun run() {
// do something
handler.postDelayed(runnableCode, 2000)
}
}
handler.post(runnableCode)
This fails to compile with "Variable ârunnableCodeâ must be initialized. I donât really understand this limitation, as the value is initialized. The only workaround I could think of was using handler.postDelayed(this, 2000), but this doesnât seem to work for SAMs:
val handler = Handler()
val runnableCode = Runnable {
// do something
handler.postDelayed(this, 2000) // this does not exist
}
handler.post(runnableCode)
this does not exist within SAM function literals (if thereâs a labeled this my IDE canât find it), and I canât find a way to access the Runnable instance itself. Is there a known workaround for this, or is it an intentional language limitation? I havenât been able to find any documentation on the subject.
I donât know the original consideration behind this, but it makes sense to me: If you want to use the âSAM function literalâ, which is more a functional programming style, âthisâ pointer is kind of confusing.
So by forcing you to use the âobject : Classâ anonymous class syntax, you will know itâs more a traditional class, where âthisâ makes more sense.
this in a lambda refers to the instance of the containing class, if any. A lambda is conceptually a function, not a class, so there is no such thing as a lambda instance to which this could refer.
The fact that a lambda can be converted into an instance of a SAM interface does not change this. Having this in a lambda mean different things depending on whether the lambda gets SAM-converted would be extremely confusing.
I understand that a SAM lambda doesnât really fit any of the rules documented at https://kotlinlang.org/docs/reference/this-expressions.html and would required a special case. I was just surprised that there was no reference to the instance being created from within itself.
It is also impossible to make them recursive or queue themselves with a Handler.
Ah, yes, that is definitely cleaner than my way. For some reason, I kept thinking I had to pass this because of the SAM conversion, but of course, the whole point of this is it avoids the SAM conversion. How silly of me Thanks for the correction!
But why using lambdas when you need a reference to the code block itself ? Thatâs what functions are about : naming a set of instructions so you can easily refer to it.
In my point of view, using lambdas for such intricated cases is harmful. You donât properly separate concerns, and prevent proper signature/documentation.
In Java FX, there is a scene: void addListener(ChangeListener<? super T> listener); by SAM.
If I can get the ref of ChangeListener that I can use removeListener(Listener).
Maybe it is more âŠpretty?