Imagine a Rock - Paper - Scissor game, it has a player versue a Host. When the game starts, the Host will wait for the player forming his/her hand shape. And while waiting, let the Host continuously forms his hand (to make it not boring).
Make an infinite loop
The pseudocode might look like this:
while (playerThinking)
randomly form a hand shape
show it to player
In Android, we have a main looper that also handles UI. If we want another infinite loop, we must not create the loop in main thread, as it’ll block the UI, which then leads to ANR (Application Not Responding).
Instead, we should create the infinite loop in another thread by using AsynTask, Handler#post() or Kotlin’s coroutine…
|
|
- #1: Add some millisecond delay to let CPU relaxed.
- #2: The function contains logic for forming the Host’s hand.
Make a blocked invocation
When the player and the Host have formed their hands, it’s time to decide who wins the round.
Assume the computation for that decision is very long, this computation should provide two things:
- It should not block the UI thread.
- It should notify the result to the Host.
One approach for solving this problem is to use a callback: The computation is brought out of main thread. And after its computation, it invokes a callback, fall back to the Host.
fun decideWinOrLose(callback)
do a long heavy computation
get result, invoke callback.onResult(result)
...
//usage
callback = {
onResult(result) = {
announce this result
}
}
decideWinOrLose(callback)
This is fine when you only have a computation. But what if you have a chains of computation, each depends on the previous one? The callback creation might become messy.
In that case, let’s convert callback to a blocked invocation:
|
|
|
|
- At #1: A callback object is created and managed by a producer.
- At #4, when the function waitGameResult exits, the calling thread is blocked/suspended. When the long computation finishes at #3, the callback is invoked. Then at #2, the
cont
object invokes its resume() function, which will unblock the calling thread at #4, the result is returned from resume() function, and is sent to the host.