Android features
part of kovenant-android
Please consult the configuration section for properly setting up Kovenant for Android.
While Kovenant is perfectly usable on Android as-is, there are a couple things that are specific to the platform. One is that Android applications can only interact with the interface through the main thread. By default Kovenant operates on its own maintained pool of threads and thus can't update the UI.
There are two ways we can achieve interacting with the main thread, besides the standard Android facilities of course.
One is by specific extensions methods and the other is by a specific Dispatcher
.
UI callbacks
The most flexible way of interacting with the main thread is by using the extension methods. The kovenant-ui
library provides successUi
, failUi
and alwaysUi
. They operate just like their
regular counterparts except their bodies are executed on the Android main thread. Both type of
callbacks can be mixed freely. If a callback is added to an already resolved Promise
this gets executed immediately
without scheduling. If you want to force scheduling just pas alwaysSchedule = true
along.
val promise = task {
foo() //produces 'bar'
}
promise success {
//no need to do this on the
//main thread
bar -> writeLog(bar)
}
promise successUi {
//also update the interface
bar -> updateUI(bar)
}
The huge advantage of this approach is that operations on the main thread are explicitly chosen. So when in doubt, this should be the preferred way of interacting with the main thread.
Start on UI thread
Just like Androids AsyncTask
you might want to do some preparations on the UI thread before you start your background
work. This is what promiseOnUi
does, it schedules a task on the UI thread and returns a Promise
on which you can
chain along. If this is called from the UI Thread this gets executed immediately without scheduling. If you want to
force scheduling just pas alwaysSchedule = true
along.
promiseOnUi {
//prepare the UI
} then {
//do background work
} successUi {
//post the results
}
Dispatcher
You can configure Kovenant to dispatch all callbacks on the main thread by using the androidUiDispatcher()
.
Please note, this approach can have a serious negative effect on Androids UI performance since you can delegate to much work to the UI thread way too easy.
That all being said. You, of course, know what you are doing.
Kovenant.context {
callbackContext.dispatcher = androidUiDispatcher()
}
Loopers
You can also create a Dispatcher based on a Looper
instance. As a prerequisite the Looper
has to be prepared already.
See Looper.prepare()
buildLooperDispatcher(looper: Looper, type: DispatcherType)
The DispatcherType
is either BASIC
(default) or FULL
. The main difference between the two types is that of
the FULL
has all the methods, like stop
and cancel
implemented where BASIC
has not. The reason for this
distinction is that keeping track of what is running and can be cancelled just uses a lot more resources. This might
not be an issue for background threads but can most certainly be an issue for the main/UI thread.
If you want to convert back and forth between Executor
s and Dispatcher
s you probably
want to use a FULL
DispatcherType
, otherwise you are better of with a BASIC
one.
Demo app
For a workable demo please checkout the Demo App on Github.