Async programming model
Most functionalities in Amplify Android are exposed as asynchronous functions. These functions return immediately, returning a result at a later time:
val post = Post.builder() .title("My First Post") .build()
// Time 0: save() is called.Amplify.DataStore.save(post, { // Time 2, later: a result or error is emitted Log.i("MyAmplifyApp", "Saved a post") }, { // Time 2, later: a result of error is emitted Log.e("MyAmplifyApp", "Save failed", it) })// Time 1: save() yields execution to following lines,// but no result available, yet.
This is a familiar pattern to many Android developers, and so is the default way of interacting with Amplify Android.
However, this development model has some challenges. Let's say you need to wait for an operation to complete, so that you can perform additional logic that depends on its result. This can quickly become unmaintainable, resulting in a situation known as "callback hell":
Consider a relational model where the creation of a Post
also requires the creation of a User
for the editor, and a PostEditor
object to link the two together:
Post post = Post.builder() .title("My First Post") .build();
User editor = User.builder() .username("Nadia") .build();
PostEditor postEditor = PostEditor.builder() .post(post) .user(editor) .build();
Using callbacks, you can save these objects via:
Amplify.DataStore.save(post, { Log.i("MyAmplifyApp", "Post saved") Amplify.DataStore.save(editor, { Log.i("MyAmplifyApp", "Editor saved") Amplify.DataStore.save(postEditor, { Log.i("MyAmplifyApp", "PostEditor saved") }, { Log.e("MyAmplifyApp", "PostEditor not saved", it) } ) }, { Log.e("MyAmplifyApp", "Editor not saved", it) } ) }, { Log.e("MyAmplifyApp", "Post not saved", it) })
After three calls, you're no longer writing down the page, you're writing down-and-right. As your program grows, this may become difficult to scale.
There are a variety of different technologies that aim to solve this particular problem: Promises/Futures, RxJava, Kotlin Coroutines, and more.
Amplify Android includes optional support for Kotlin Coroutines and RxJava.