# Building an Android Emoji Garden on Jetpack Compose with Realm

As an Android developer, have you wanted to get acquainted with Jetpack
Compose and mobile architecture? Or maybe you have wanted to build an
app end to end, with a hosted database? If yes, then this post is for
you!

We'll be building an app that shows data from a central shared database:
MongoDB Realm. The app will reflect changes in the database in real-time on all devices that use it.

Imagine you're at a conference and you'd like to engage with the other
attendees in a creative way. How about with emojis? 😋 What if the
conference had an app with a field of emojis where each emoji represents
an attendee? Together, they create a beautiful garden. I call this app
*Emoji Garden*. I'll be showing you how to build such an app in this
post.

This article is Part 1 of a two-parter where we'll just be building the
core app structure and establishing the connection to Realm and sharing
our emojis between the database and the app. Adding and changing emojis
from the app will be in Part 2.

Here we see the app at first run. We'll be creating two screens:

1. A **Login Screen**.
2. An **Emoji Garden Screen** updated with emojis directly from the
server. It displays all the attendees of the conference as emojis.

Looks like a lot of asynchronous code, doesn't it? As we know,
asynchronous code is the bane of Android development. However, you
generally can't avoid it for database and network operations. In our
app, we store emojis in the local Realm database. The local database
seamlessly syncs with a MongoDB Realm Sync server instance in the
background. Are we going to need other libraries like RxJava or
Coroutines? Nope, we won't. **In this article, we'll see how to get**
Realm to do this all for you!

If you prefer Kotlin Flows with Coroutines, then don't worry. The Realm
SDK can generate them for you. I'll show you how to do that too. Let's
begin!

Let me tempt you with the tech for Emoji Garden!

* Using Jetpack Compose to put together the UI.
* Using ViewModels and MVVM effectively with Compose.
* Using Coroutines
and Realm functions to keep your UI updated.
* Using anonymous logins in Realm.
* Setting up a globally accessible MongoDB Atlas instance to sync to
your app's Realm database.

## Prerequisites

Remember that all of the code for the final app is available in the
GitHub repo. If
you'd like to build Emoji Garden🌲 with me, you'll need the following:

1. Android Studio, version
"*Arctic Fox (2020.3.1)*" or later.
2. A basic understanding of
building Android apps, like knowing what an Activity is and having tried a bit of Java or Kotlin coding.

Emoji Garden shouldn't be the first Android app you've ever tried to
build. However, it is a great intro into Realm and Jetpack Compose.

> 💡 There's one prerequisite you'd need for anything you're doing and
> that's a growth mindset 🌱. It means you believe you can learn anything. I believe in you!

Estimated time to complete: 2.5-3 hours

## Create a New Compose Project

Once you've got the Android Studio
Canary, you can fire up
the **New Project** menu and select Empty Compose Activity. Name your
app "Emoji Garden" if you want the same name as mine.

## Project Imports

We will be adding imports into two files:

1. Into the app level build.gradle.
2. Into the project level build.gradle.

At times, I may refer to functions, classes, or variables by putting
their names in italics, like *EmojiClass*, so you can tell what's a
variable/constant/class and what isn't.

### App Level build.gradle Imports

First, the app level build.gradle. To open the app's build.gradle file,
double-tap Shift in Android Studio and type "build.gradle." **Select the**
one with "app" at the end and hit enter. Check out how build.gradle
looks in the finished sample
app.
Yours doesn't need to look exactly like this yet. I'll tell you what to
add.

In the app level build.gradle, we are going to add a few dependencies,
shown below. They go into the *dependencies* block:

``` kotlin
// For the viewModel function that imports them into activities
implementation 'androidx.activity:activity-ktx:1.3.0'

// For the ViewModelScope if using Coroutines in the ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
```

**After** adding them, your dependencies block should look like this.
You could copy and replace the entire block in your app.

``` kotlin
dependencies {

   implementation 'androidx.core:core-ktx:1.3.2'
   implementation 'androidx.appcompat:appcompat:1.2.0'
   implementation 'com.google.android.material:material:1.2.1'

   // For Jetpack Compose
   implementation "androidx.compose.ui:ui:$compose_version"
   implementation "androidx.compose.material:material:$compose_version"
   implementation "androidx.compose.ui:ui-tooling:$compose_version"

   // For the viewModel function that imports them into activities
   implementation 'androidx.activity:activity-ktx:1.3.0'

   // For the ViewModelScope if using Coroutines in the ViewModel
   implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
   implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'

   testImplementation 'junit:junit:4.+'
   androidTestImplementation 'androidx.test.ext:junit:1.1.2'
   androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
```

In the same file under *android* in the app level build.gradle, you
should have the *composeOptions* already. **Make sure the**
kotlinCompilerVersion is at least 1.5.10. Compose needs this to
function correctly.

``` kotlin
composeOptions {
   kotlinCompilerExtensionVersion compose_version
   kotlinCompilerVersion kotlin_ext
}
```

### Project Level build.gradle Imports

Open the **project level** build.gradle file. Double-tap Shift in
Android Studio -> type "build.gradle" and **look for the one with a dot**
at the end. This is how it looks in the sample app.
Follow along for steps.

Make sure the compose version under buildscript is 1.x.x or greater.

``` kotlin
buildscript {
   ext {
      compose_version = '1.0.0'
      kotlin_ext = '1.5.10'
   }
```

Great! We're all done with imports. Remember to hit "Sync Now" at the
top right.

## Overview of the Emoji Garden App

### Folder Structure

*com.example.emojigarden* is the directory where all the code for the
Emoji Garden app resides. This directory is auto-generated from the app
name when you create a project. The image shown below is an overview of
all the classes in the finished app. It's what we'll have when we're
done with this article.

## Building the Android App

The Emoji Garden app is divided into two parts: the UI and the logic.

1. The UI displays the emoji garden.
2. The logic (classes and functions) will update the emoji garden from
the server. This will keep the app in sync for all attendees.

### Creating a New Source File

Let's create a file named *EmojiTile* inside a source folder. If you're
not sure where the source folder is, here's how to find it. Hit the
project tab (**⌘+1** on mac or **Ctrl+1** on Windows/Linux).

Open the app folder -> java -> *com.example.emojigarden* or your package name. Right click on *com.example.emojigarden* to create new files for source code. For this project, we will create all source files here. To see other strategies to organize code, see package-by-feature.

Type in the name of the class you want to make— *EmojiTile*, for
instance. Then hit Enter.

### Write the Emoji Tile Class

Since the garden is full of emojis, we need a class to represent the
emojis. Let's make the *EmojiTile* class for this. Paste this in.

``` kotlin
class EmojiTile {
   var emoji : String = ""
}
```

### Let's Start with the Garden Screen

Here's what the screen will look like. When the UI is ready, the Garden
Screen will display a grid of beautiful emojis. We still have some work
to do in setting everything up.

#### The Garden UI Code

Let's get started making that screen. We're going to throw away nearly
everything in *MainActivity.kt* and write this code in its place.

Reach *MainActivity.kt* by **double-tapping Shift** and typing
"mainactivity." Any of those three results in the image below will take
you there.

Here's what the file looks like before we've made any changes.

Now, leave only the code below in *MainActivity.kt* apart from the
imports. Notice how we've removed everything inside the *setContent*
function except the MainActivityUi function. We haven't created it yet,
so I've left it commented out. It's the last of the three sectioned UI
below. The extra annotation (*@ExperimentalFoundationApi*) will be
explained shortly.

``` kotlin
@ExperimentalFoundationApi
class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContent {
         // MainActivityUi(emptyList())

      }
   }
}
```

The UI code for the garden will be built up in three functions. Each
represents one "view."

> 💡 We'll be using a handful of functions for UI instead of defining it
> in the Android XML file. Compose uses only regular functions marked
> @Composeable to define how the UI should look. Compose also features interactive Previews without even deploying to an emulator or device. "Functions as UI" make UIs designed in Jetpack Compose incredibly modular.

The functions are:

1. *EmojiHolder*
2. *EmojiGrid*
3. *MainActivityUi*

I'll show how to do previews right after the first function EmojiHolder.
Each of the three functions will be written at the end of the
*MainActivity.kt* file. That will put the functions outside the
*MainActivity* class. **Compose functions are independent of classes.**
They'll be composed together like this:

> 💡 Composing just means using inside something else—like calling one
> Jetpack Compose function inside another Jetpack Compose function.

### Single Emoji Holder

Let's start from the smallest bit of UI, the holder for a single emoji.

``` kotlin
@Composable
fun EmojiHolder(emoji: EmojiTile) {
   Text(emoji.emoji)
}
```

The *EmojiHolder* function draws the emoji in a text box. The text
function is part of Jetpack Compose. It's the equivalent of a TextView
in the XML way making UI. It just needs to have some text handed to it.
In this case, the text comes from the *EmojiTile* class.

### Previewing Your Code

A great thing about Compose functions is that they can be previewed
right inside Android Studio. Drop this function into *MainActivity.kt*
at the end.

``` kotlin
@Preview
@Composable
fun EmojiPreview() {
   EmojiHolder(EmojiTile().apply { emoji = "😼" })
}
```

You'll see the image below! If the preview is too small, click it and
hit **Ctrl+** or **⌘+** to increase the size. If it's not, choose the
"Split View" (the larger arrow below). It splits the screen between code
and previews. Previews are only generated once you've changed the code and hit the build icon. To rebuild the code, hit the refresh icon (the
smaller green arrow below).

### The EmojiGrid

To make the garden, we'll be using the *LazyVerticalGrid*, which is like
RecyclerView in Compose. It only renders items that are visible, as opposed to those
that scroll offscreen. *LazyVerticalGrid* is a new class in Jetpack
Compose version alpha9. Since it's experimental, it requires the
*@ExperimentalFoundationApi* annotation. It's fun to play with though!
Copy this into your project.

``` kotlin
@ExperimentalFoundationApi
@Composable
fun EmojiGrid(emojiList: List) {

   LazyVerticalGrid(cells = GridCells.Adaptive(20.dp)) {
      items(emojiList) { emojiTile ->
         EmojiHolder(emojiTile)
      }
   }
}
```

### Garden Screen Container: MainActivityUI

Finally, the EmojiGrid is centered in a full-width *Box*. *Box* itself
is a compose function.

> 💡 Since my app was named "Emoji Garden," the auto-generated theme for it is EmojiGardenTheme. The theme name may be different for you. Type it in, if so.

Since the *MainActivityUi* is composed of *EmojiGrid*, which uses the
*@ExperimentalFoundationApi* annotation, *MainActivityUi* now has to use the same annotation.

``` kotlin
@ExperimentalFoundationApi
@Composable
fun MainActivityUi(emojiList: List) {
   EmojiGardenTheme {
      Box(
         Modifier.fillMaxWidth().padding(16.dp),
         contentAlignment = Alignment.Center
      ) {
         EmojiGrid(emojiList)
      }
   }
}
```

### Previews

Try previews for any of these! Here's a preview function for
*MainActivityUI*. Preview functions should be in the same file as the
functions they're trying to preview.

``` kotlin
@ExperimentalFoundationApi
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
   MainActivityUi(List(102){ i -> EmojiTile().apply  { emoji = emojisi] }})
}

val emojis = listOf("🐤","🐦","🐔","🦤","🕊","️","🦆","🦅","🪶","🦩","🐥","-","🐣","🦉","🦜","🦚","🐧","🐓","🦢","🦃","🦡","🦇","🐻","🦫","🦬","🐈","‍","⬛","🐗","🐪","🐈","🐱","🐿","️","🐄","🐮","🦌","🐕","🐶","🐘","🐑","🦊","🦒","🐐","🦍","🦮","🐹","🦔","🦛","🐎","🐴","🦘","🐨","🐆","🦁","🦙","🦣","🐒","🐵","🐁","🐭","🦧","🦦","🐂","🐼","🐾","🐖","🐷","🐽","🐻","‍","❄","️","🐩","🐇","🐰","🦝","🐏","🐀","🦏","🐕","‍","🦺","🦨","🦥","🐅","🐯","🐫","-","🦄","🐃","🐺","🦓","🐳","🐡","🐬","🐟","🐙","🦭","🦈","🐚","🐳","🐠","🐋","🌱","🌵","🌳","🌲","🍂","🍀","🌿","🍃","🍁","🌴","🪴","🌱","☘","️","🌾","🐊","🐊","🐉","🐲","🦎","🦕","🐍","🦖","-","🐢")
```

Here's a preview generated by the code above. Remember to hit the build arrows if it doesn't show up.

You might notice that some of the emojis aren't showing up. That's
because we haven't begun to use [EmojiCompat yet. We'll get to that in the next article.

### Login Screen

You can use a Realm database locally without logging in. Syncing data
requires a user account. Let's take a look at the UI for login since
we'll need it soon. If you're following along, drop this into the
*MainActivity.kt*, at the end of the file. The login screen is going to
be all of one button. Notice that the actual login function is passed
into the View. Later, we'll make a *ViewModel* named *LoginVm*. It will
provide the login function.

``` kotlin
@Composable
fun LoginView(login : () -> Unit) {
   Column(modifier = Modifier.fillMaxWidth().padding(16.dp),
      verticalArrangement = Arrangement.Center,
      horizontalAlignment = Alignment.CenterHorizontally){

      Button(login){
         Text("Login")
      }
   }
}
```

## Set Up Realm Sync

We've built as much of the app as we can without Realm. Now it's time to enable storing our emojis locally. Then we can begin syncing them to
your own managed Realm instance in the cloud.

Now we need to:

1. Create a free MongoDB Atlas
account
    * Follow the link above to host your data in the cloud. The emojis
    in the garden will be synced to this database so they can be
    sent to all connecting mobile devices. Configure your Atlas
    account with the following steps:
    * Add your connection
    IP,
    so only someone with your IP can access the database.
    * Create a database
    user,
    so you have an admin user to run commands with. Note down the
    username and password you create here.
2. Create a Realm App on the cloud account
    * Hit the Realm tab
    * 
    * You're building a Mobile app for Android from scratch. How cool!
    Hit Start a New realm App.
    * 
    * You can name your application anything you want. Even the
    default "Application 0" is fine.
3. Turn on Anonymous
authentication \- We don't want to make people wait around to authenticate with a
username and password. So, we'll just hand them a login button
that will perform an anonymous authentication. Follow the link
in the title to turn it on.
4. Enable Realm Sync
    * This will allow real-time data synchronization between mobile
    clients.
    * Go to https://cloud.mongodb.com and hit the Realm tab.
    * Click your application. It might have a different name.
    * 
    * As in the image below, hit Sync (on the left) in the Realm tab.
    Then "Define Data Models" on the page that opens.
    * 
    * Choose the default cluster. For the partition key, type in
    "event" and select a type of "string" for it. Under "Define a
    database name," type in "gardens." Hit "Turn Dev Mode On" at the
    bottom.
    * 

> 💡 For this use case, the "partition key" should be named "event" and be
> of type "String." We'll see why when we add the partition key to our
> EmojiTile later. The partition key is a way to separate data within the
> collection by when it's going to be used.

Fill in those details and hit "Turn Dev Mode On." Now click "Review and
Deploy."

## Integrating Realm into the App

### Install the SDK

Install the Realm Android
SDK

Follow the link above to install the SDK. This provides Realm
authentication and database methods within the app. When they talk about
adding "apply plugin:" just replace that with "id," like in the image
below:

### Add Internet Permissions

Open the AndroidManifest.xml file by **double-tapping Shift** in Android
Studio and typing in "manifest."

Add the Internet permission to your Android Manifest above the
application tag.

``` xml

```

The file should start off like this after adding it:

``` xml

   

    💡 "event" might seem a strange name for a field for an emoji. Here,
> it's the partition key. Emojis for a single garden will be assigned the
> same partition key. Each instance of Realm on mobile can only be
> configured to retrieve objects with one partition key.

### Separating Your Concerns

We're going to need objects from the Realm Mobile SDK that give access
to login and data functions. These will be abstracted into their own
class, called RealmModule.

Later, I'll create a custom application class *EmojiGardenApplication*
to instantiate *RealmModule*. This will make it easy to pass into the
*ViewModels*.

#### RealmModule

Grab a copy of the RealmModule from the sample
repo.
This will handle Realm App initialization and connecting to a synced
instance for you. It also contains a method to log in. Copy/paste it
into the source folder. You might end up with duplicate *package*
declarations. Delete the extra one, if so. Let's take a look at what's
in *RealmModule*. Skip to the next section if you want to get right to using it.

##### The Constructor and Class Variables

The init{ } block is like a Kotlin constructor. It'll run as soon as an
instance of the class is created. Realm.init is required for local or
remote Realms. Then, a configuration is created from your appId as part
of initialization, as seen
here. To get
a synced realm, we need to log in.

We'll need to hold onto the Realm App object for logins later, so it's a
class variable.

``` kotlin
private var syncedRealm: Realm? = null
private val app : App
private val TAG = RealmModule::class.java.simpleName

init {
   Realm.init(application)
   app = App(AppConfiguration.Builder(appId).build())

   // Login anonymously because a logged in user is required to open a synced realm.
   loginAnonSyncedRealm(
      onSuccess = {Log.d(TAG, "Login successful") },
      onFailure = {Log.d(TAG, "Login Unsuccessful, are you connected to the net?")}
   )
}
```

##### The Login Function

Before you can add data to a synced Realm, you need to be logged in. You
only need to be online the first time you log in. Your credentials are
preserved and data can be inserted offline after that.

Note the partition key. Only objects with the same value for the
partition key as specified here will be synced by this Realm instance.
To sync objects with different keys, you would need to create another
instance of Realm. Once login succeeds, the logged-in user object is
used to instantiate the synced Realm.

``` kotlin
fun loginAnonSyncedRealm(partitionKey : String = "default", onSuccess : () -> Unit, onFailure : () -> Unit ) {

   val credentials = Credentials.anonymous()

   app.loginAsync(credentials) { loginResult ->
      Log.d("RealmModule", "logged in: $loginResult, error? : ${loginResult.error}")
      if (loginResult.isSuccess) {
         instantiateSyncedRealm(loginResult.get(), partitionKey)
         onSuccess()
      } else {
         onFailure()
      }
   }

}

private fun instantiateSyncedRealm(user: User?, partition : String) {
   val config: SyncConfiguration = SyncConfiguration.defaultConfig(user, partition)
   syncedRealm = Realm.getInstance(config)
}
```

##### Initialize the Realm Schema

Part of the setup of Realm is telling the server a little about the data
types it can expect. This is only important for statically typed
programming languages like Kotlin, which would refuse to sync objects
that it can't cast into expected types.

> 💡 There are a few ways to do this:
> 
> 
> 1. Manually code the schema as a JSON schema document.
> 2. Let Realm generate the schema from what's stored in the database already.
> 3. Let Realm figure out the schema from the documents at the time they're pushed into the db from the mobile app.
> 
> 
> We'll be doing #3.

If you're wondering where the single soil emoji comes from when you log
in, it's from this function. It will be called behind the scenes (in
*LoginVm*) to set up the schema for the *EmojiTile* collection. Later,
when we add emojis from the server, it'll have stronger guarantees about
what types it contains.

``` kotlin
fun initializeCollectionIfEmpty() {
   syncedRealm?.executeTransactionAsync { realm ->
      if (realm.where(EmojiTile::class.java).count() == 0L) {
         realm.insert(EmojiTile().apply {
               emoji = "🟫"
         })
      }
   }
}
```

##### Minor Functions

*getSyncedRealm* Required to work around the fact that *syncedRealm*
must be nullable internally. The internal nullability is used to figure
out whether it's initialized. When it's retrieved externally, we'd
always expect it to be available and so we throw an exception if it
isn't.

``` kotlin
fun isInitialized() = syncedRealm != null

fun getSyncedRealm() : Realm = syncedRealm ?: throw IllegalStateException("loginAnonSyncedRealm has to return onSuccess first")
```

### EmojiGarden Custom Application

Create a custom application class for the Emoji Garden app which will
instantiate the *RealmModule*.

Remember to add your appId to the appId variable. You could name the new
class *EmojiGardenApplication*.

``` kotlin
class EmojiGardenApplication : Application() {
   lateinit var realmModule : RealmModule

   override fun onCreate() {
      super.onCreate()

      // Get your appId from https://realm.mongodb.com/ for the database you created under there.
      val appId = "your appId here"
      realmModule = RealmModule(this, appId)
   }
}
```

## ViewModels

ViewModels hold the logic and data for the UI. There will be one
ViewModel each for the Login and Garden UIs.

### Login ViewModel

What the *LoginVm* does:

1. An anonymous login.
2. Initializing the MongoDB Realm Schema.

Copy *LoginVm*'s complete code from
here.

Here's how the *LoginVm* works:

1. Retrieve an instance of the RealmModule from the custom application.
2. Once login succeeds, it adds initial data (like a 🟫 emoji) to the
database to initialize the Realm schema.

> 💡 Initializing the Realm schema is only required right now because the
> app doesn't provide a way to choose and insert your emojis. At least one
> inserted emoji is required for Realm Sync to figure out what kind of
> data will be synced. When the app is written to handle inserts by
> itself, this can be removed.

*showGarden* will be used to "switch" between whether the Login screen
or the Garden screen should be shown. This will be covered in more
detail later. It is marked
"*private set*" so that it can't be modified from outside *LoginVm*.

``` kotlin
var showGarden : Boolean by mutableStateOf(getApplication().realmModule.isInitialized())
   private set
```

*initializeData* will insert a sample emoji into Realm Sync. When it's
done, it will signal for the garden to be shown. We're going to call
this after *login*.

``` kotlin
private fun initializeData() {
   getApplication().realmModule.initializeCollectionIfEmpty()
   showGarden = true
}
```

*login* calls the equivalent function in *RealmModule* as seen earlier.
If it succeeds, it initializes the data. Failures are only logged, but
you could do anything with them.

``` kotlin
fun login() = getApplication().realmModule.loginAnonSyncedRealm(
         onSuccess = ::initializeData,
         onFailure = { Log.d(TAG, "Failed to login") }
      )
```

You can now modify *MainActivity.kt* to display and use Login. You might
need to *import* the *viewModel* function. Android Studio will give you
that option.

``` kotlin
@ExperimentalFoundationApi
class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContent {
         val loginVm : LoginVm = viewModel()
         if(!loginVm.showGarden) {
            LoginView(loginVm::login)
         }
      }
   }
}
```

Once you've hit login, the button will disappear, leaving you a blank
screen. Let's understand what happened and get to work on the garden
screen, which should appear instead.

> 💡 If you get an error like "Caused by: java.lang.ClassCastException:
> android.app.Application cannot be cast to EmojiGardenApplication at
> com.example.emojigarden.LoginVm.\(LoginVm.kt:20)," then you might
> have forgotten to add the EmojiGardenApplication to the name attribute in the manifest.

### What Initialization Did

Here's how you can verify what happened because of the initialization.
Before logging in and sending the first *EmojiTile*, you could go look
up your data's schema by going to https://cloud.mongodb.com in the
Realm tab. Click Schema on the options on the left and you'd see this:

MongoDB Realm Sync has inferred the data types in EmojiTile when the
first EmojiTile was pushed up. Here's what that section says now
instead:

If we had inserted data on the server side prior to this, it would've
defaulted the *index* field type to *Double* instead. The Realm SDK
would not have been able to coerce it on mobile, and sync would've
failed.

### The Garden ViewModel

The UI code is only going to render data that is given to them by the
ViewModels, which is why if you run the app without previews, everything
has been blank so far.

As a refresher, we're using the MVVM architecture, and we'll be using Android ViewModels.
The ViewModels that we'll be using are custom classes that extend the
ViewModel class. They implement their own methods to retrieve and hold
onto data that UI should render. In this case, that's the EmojiTile
objects that we'll be loading from the MongoDB Realm Sync server.

I'm going to demonstrate two ways to do this:

1. With Realm alone handling the asynchronous data retrieval via Realm
SDK functions. In the class EmojiVmRealm.
2. With Kotlin Coroutines Flow handling the data being updated
asynchronously, but with Realm still providing the data. In the
class EmojiVmFlow.

Either way is fine. You can pick whichever way suits you. You could even
swap between them by changing a single line of code. If you would like
to avoid any asynchronous handling of data by yourself, use
EmojiVmRealm and let Realm do all the heavy lifting!
If you are already using Kotlin Flows, and would like to use that model
of handling asynchronous operations, use EmojiVmFlow.

###### Here's what's common to both ViewModels.

Take a look at the code of EmojiVmRealm and EmojiVmFlow side by side.

Here's how they work:

1. The *emojiState* variable is observed by Compose since it's created via the mutableStateOf. It allows Jetpack Compose to observe and react to values when they change to redraw the UI. Both ViewModels will get data from the Realm database and update the emojiState variable with it. This separates the code for how the UI is rendered from how the data for it is retrieved.
2. The ViewModel is set up as an AndroidViewModel to allow it to receive an Application object.
3. Since Application is accessible from it, the RealmModule can be pulled in.
4. RealmModule was instantiated in the custom application so that it could be passed to any ViewModel in the app.
    * We get the Realm database instance from the RealmModule via getSyncedRealm.
    * Searching for EmojiTile objects is as simple as calling where(EmojiTile::class.java).
    * Calling .sort on the results of where sorts them by their index in ascending order.
    * They're requested asynchronously with findAllAsync, so the entire operation runs in a background thread.

### EmojiVmRealm

EmojiVmRealm is a class that extends
ViewModel.
Take a look at the complete code
and copy it into your source folder. It provides logic operations and updates data to the Jetpack Compose UI. It uses standard Realm SDK functionality to asynchronously load up the emojis and order them for display.

Apart from what the two ViewModels have in common, here's how this class works:

#### Realm Change Listeners

A change listener watches for changes in the database. These changes might come from other people setting their emojis in their own apps.

``` kotlin
private val emojiTilesResults : RealmResults =  getApplication().realmModule
   .getSyncedRealm()
   .where(EmojiTile::class.java)
   .sort(EmojiTile::index.name)
   .findAllAsync()
   .apply {
      addChangeListener(emojiTilesChangeListener)
   }
```

> 💡 The Realm change listener is at the heart of reactive programming with Realm.

``` kotlin
private val emojiTilesChangeListener  =
   OrderedRealmCollectionChangeListener> { updatedResults, _ ->
      emojiState = updatedResults.freeze()
   }
```

The change listener function defines what happens when a change is
detected in the database. Here, the listener operates on any collection
of *EmojiTiles* as can be seen from its type parameter of
*RealmResults\*. In this case, when changes are detected, the
*emojiState* variable is reassigned with "frozen" results.

The freeze function is part of the Realm SDK and makes the object
immutable. It's being used here to avoid issues when items are deleted
from the server. A delete would invalidate the Realm object, and if that
object was providing data to the UI at the time, it could lead to
crashes if it wasn't frozen.

#### MutableState: emojiState

``` kotlin
import androidx.compose.runtime.getValue
import androidx.compose.runtime.neverEqualPolicy
import androidx.compose.runtime.setValue

   var emojiState : List by mutableStateOf(listOf(), neverEqualPolicy())
      private set
```

*emojiState* is a *mutableStateOf* which Compose can observe for
changes. It's been assigned a *private set*, which means that its value
can only be set from inside *EmojiVmRealm* for code separation. When a
change is detected, the *emojiState* variable is updated with results.
The changeset isn't required so it's marked "\_".

*neverEqualPolicy* needs to be specified since Mutable State's default
structural equality check doesn't see a difference between updated
*RealmResults*. *neverEqualPolicy* is then required to make it update. I
specify the imports here because sometimes you'd get an error if you
didn't specifically import them.

``` kotlin
private val emojiTilesChangeListener  =
   OrderedRealmCollectionChangeListener> { updatedResults, _ ->
   emojiState = updatedResults.freeze()
}
```

Change listeners have to be released when the ViewModel is being
disposed. Any resources in a ViewModel that are meant to be released
when it's being disposed should be in onCleared.

``` kotlin
override fun onCleared() {
   super.onCleared()
   emojiTilesResults.removeAllChangeListeners()
}
```

### EmojiVmFlow

*EmojiVmFlow* offloads some asynchronous operations to Kotlin Flows while still retrieving data from Realm. Take a look at it in the sample repo here, and copy it to your app.

Apart from what the two ViewModels have in common, here's what this VM does:

The toFlow operator from the Realm SDK automatically retrieves the list of emojis when they're updated on the server.

``` kotlin
private val _emojiTiles : Flow> =  getApplication().realmModule
   .getSyncedRealm()
   .where(EmojiTile::class.java)
   .sort(EmojiTile::index.name)
   .findAllAsync()
   .toFlow()
```

The flow is launched in
viewModelScope
to tie it to the ViewModel lifecycle. Once collected, each emitted list
is stored in the emojiState variable.

``` kotlin
init {
   viewModelScope.launch {
      _emojiTiles.collect {
            emojiState = it
      }
   }
}
```

Since *viewModelScope* is a built-in library scope that's cleared when
the ViewModel is shut down, we don't need to bother with disposing of
it.

## Switching UI Between Login and Gardens

As we put both the screens together in the view for the actual Activity,
here's what we're trying to do:

First, connect the *LoginVm* to the view and check if the user is
authenticated. Then:

* If authenticated, show the garden.
* If not authenticated, show the login view.
* This is done via *if(loginVm.showGarden)*.

Take a look at the entire
activity
in the repo. The only change we'll be making is in the *onCreate*
function. In fact, only the *setContent* function is modified to
selectively show either the Login or the Garden Screen
(*MainActivityUi*). It also connects the ViewModels to the Garden Screen
now.

The *LoginVm* internally maintains whether to *showGarden* or not based
on whether the login succeeded. If this succeeds, the garden screen
*MainActivityUI* is instantiated with its own ViewModel, supplying the
emojis it gathers from Realm. If the login hasn't happened, it shows the
login view.

> 💡 The code below uses EmojiVmRealm. If you were using EmojiVmFlow, just type in EmojiVmFlow instead. Everything will just work.

``` kotlin
@ExperimentalFoundationApi
class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContent {
         val loginVm : LoginVm = viewModel()

         if(loginVm.showGarden){
               val model : EmojiVmRealm = viewModel()
               MainActivityUi(model.emojiState)
         } else
         {
               LoginView(loginVm::login)
         }

      }
   }
}
```

## Tending the Garden Remotely

Here's what you'll have on your app once you're all logged in and the
garden screen is hooked up too: a lone 🟫 emoji on a vast, empty screen.

Let's move to the server to add some more emojis and let the server
handle sending them back to the app! Every user of the app will see the
same list of emojis. I'll show how to insert the emojis from the web
console.

Open up https://cloud.mongodb.com again. Hit *collections*. *Insert*
document will appear at the middle right. Then hit *insert document*.

Hit the curly braces so you can copy/paste
this
huge pile of emojis into it.

You'll have all these emojis we just added to the server pop up on the
device. Enjoy your critters!

Feel free to play around with the console. Change the emojis in
collections by double-clicking them.

## Summary

This has been a walkthrough for how to build an Android app that
effectively uses Compose and Realm together with the latest techniques
to build reactive apps with very little code.

In this article, we've covered:

* Using the MVVM architectural pattern with Jetpack Compose.
* Setting up MongoDB Realm.
* Using Realm in ViewModels.
* Using Realm to Kotlin Flows in ViewModels.
* Using anonymous authentication in Realm.
* Building Conditional UIs with Jetpack Compose.

There's a lot here to add to any of your projects. Feel free to use any
parts of this walkthrough or use the whole thing! I hope you've gotten
to see what MongoDB Realm can do for your mobile apps!

## What's Next?

In Part 2, I'll get to best practises for dealing with emojis using
EmojiCompat.
I'll also get into how to change the emojis from the device itself and
add some personalization that will enhance the app's functionality. In
addition, we'll also have to add some "rules" to handle use cases—for
example, users can only alter unclaimed "soil" tiles and handle conflict
resolution when two users try to claim the same tile simultaneously.
What happens when two people pick the same tiles at nearly the same
time? Who gets to keep it? How can we avoid pranksters changing our own
emojis? These questions and more will be answered in Part 2.

## References

Here's some additional reading if you'd like to learn more about what we
did in this article.

1. The official docs on Compose layout are incredible to see Compose's flexibility.
2. The codelabs teach this method of handling state.
3. All the code for this project.
4. Also, thanks to Monica Dinculescu for coming up with the idea for the garden on the web. This is an adaptation of her ideas.

> If you have questions, please head to our developer community
> website where the MongoDB engineers and
> the MongoDB community will help you build your next big idea with
> MongoDB.