Page updated Nov 8, 2023

Async programming model

Most functionalities in Amplify Android are exposed as asynchronous functions. These functions return immediately, returning a result at a later time:

1val post = Post.builder()
2 .title("My First Post")
3 .build()
4
5// Time 0: save() is called.
6Amplify.DataStore.save(post,
7 {
8 // Time 2, later: a result or error is emitted
9 Log.i("MyAmplifyApp", "Saved a post")
10 },
11 {
12 // Time 2, later: a result of error is emitted
13 Log.e("MyAmplifyApp", "Save failed", it)
14 }
15)
16// Time 1: save() yields execution to following lines,
17// 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:

1Post post = Post.builder()
2 .title("My First Post")
3 .build();
4
5User editor = User.builder()
6 .username("Nadia")
7 .build();
8
9PostEditor postEditor = PostEditor.builder()
10 .post(post)
11 .user(editor)
12 .build();

Using callbacks, you can save these objects via:

1Amplify.DataStore.save(post,
2 {
3 Log.i("MyAmplifyApp", "Post saved")
4 Amplify.DataStore.save(editor,
5 {
6 Log.i("MyAmplifyApp", "Editor saved")
7 Amplify.DataStore.save(postEditor,
8 { Log.i("MyAmplifyApp", "PostEditor saved") },
9 { Log.e("MyAmplifyApp", "PostEditor not saved", it) }
10 )
11 },
12 { Log.e("MyAmplifyApp", "Editor not saved", it) }
13 )
14 },
15 { Log.e("MyAmplifyApp", "Post not saved", it) }
16)

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.