Object in Kotlin and the Singleton Pattern

Learn how to use the object keyword in Kotlin to define singleton, companion and anonymous objects and to ensure Java interoperability. By Caio Fukelmann Landau.

4.3 (4) · 1 Review

Download materials
Save for later
Share

When working in Kotlin, you’ll often come across a keyword called object. This keyword has different meanings depending on its context.

In this tutorial, you’ll build a shopping app to learn about the many uses of object. In this app, users can browse products, add them to their shopping cart and clear the cart. While building this app, you’ll learn:

  • How to define singleton, companion and anonymous objects.
  • Object expressions.
  • Java interoperability: How to expose objects to Java callers.
  • Singleton best practices.

It’s time to get started!

Note: This tutorial assumes familiarity with Kotlin for Android development. If you’d like to revisit the basics of Kotlin, consider reading Kotlin for Android: An Introduction.

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

Open your project in Android Studio 4.1 or higher. Select Open an Existing Project and then select the name of the starter project.

Instructions for opening a project in Android Studio

When you open the starter project, you’ll see some structure already in place:

  1. MainActivity.kt: Your app’s initial screen.
  2. Product.kt: A model representing a product in the store.
  3. ProductListAdapter.kt: A ListAdapter, which both MainActivity and ShoppingCartActivity use to populate a RecyclerView of products.
  4. ShoppingCartActivity.kt: An activity you’ll use to display the user’s shopping cart, total price and a button to clear the cart.
  5. StringUtils.kt: Contains a handy extension on Int to format it to a price string like $12.34.

Next, build and run the project. You’ll see a screen with a variety of Android-themed products for sale:

Smar-T-Shop with products for sale along with their prices

However, you can’t buy anything just yet. Keep reading to implement this shopping experience while learning about the many uses for the object keyword in Kotlin.

Note: For more details about RecyclerView, read our Android RecyclerView Tutorial. For details about Kotlin extensions, check out our Extension Functions and Properties Tutorial.

Using Singletons in Kotlin

By using the keyword object in your app, you’re defining a singleton. A singleton is a design pattern in which a given class has only one single instance inside the entire app. A singleton’s two most common use cases are:

  1. To share data between two otherwise unrelated areas of your project.
  2. To share logic that doesn’t have associated state throughout the app.

Keep in mind that singletons are not a data persistence solution. Data in singletons live only as long as your app is in memory.

Read on to learn how to define a singleton!

Using Object to Define a Shopping Cart Singleton

Currently, there’s no way to add items to your cart and view them in the app. To do that, you need a place to put that information and a way to share it across screens of your app.

You’re going to use the power of the object keyword to manage this through a ShoppingCart singleton. To create app ▸ src ▸ main ▸ java ▸ com ▸ raywenderlich ▸ android ▸ kotlinobject ▸ ShoppingCart.kt and use object to define the ShoppingCart, take the following steps:

  1. In Android Studio, select File ▸ New ▸ Kotlin File/Class.
  2. In the pop-up, name your file ShoppingCart, select Object and press Enter.

Android Studio pop-up to create a ShoppingCart singleton

Android Studio will create a file with an empty object for you. It will look like this:

object ShoppingCart {
}

Notice how much this object declaration looks like a Kotlin class! The only difference is that you’re using the object keyword instead of the class keyword. But what difference does that make?

You can learn a lot about this difference by looking at the equivalent Java code. Lucky for you, Android Studio has a way for you to do this.

Go to Tools ▸ Kotlin ▸ Show Kotlin Bytecode and click the Decompile button at the top of the Kotlin Bytecode window. You’ll see something like the following:

public final class ShoppingCart {
   @NotNull
   public static final ShoppingCart INSTANCE;

   private ShoppingCart() {
   }

   static {
      ShoppingCart var0 = new ShoppingCart();
      INSTANCE = var0;
   }
}

The main points to notice here are:

  • The Java class has a private constructor.
  • It has a static INSTANCE of the ShoppingCart singleton for the calling code to use.

Remember this when you’re trying to use this Kotlin code alongside Java!

Creating a Singleton’s Public Interface

Now that you’ve created your singleton, you need to create its public interface so other classes can communicate with it. To do this, add the following insideShoppingCart‘s curly brackets:

// 1.
var products: List<Product> = emptyList()
  private set

// 2.
fun addProduct(product: Product) {
  products = products + listOf(product)
}

// 3.
fun clear() {
  products = emptyList()
}

By adding the above code, you:

  1. Created a list of Products. These are the products the user added to their cart. It has a private setter because only the singleton should be able to directly modify the list.
  2. Created a function to append the added product to the products list in the shopping cart. MainActivity will call this public function when a user adds a product to their cart.
  3. Gave the user a way to clear their shopping cart. Calling this function will empty the products list held by ShoppingCart.

Next, you’ll learn how to access the public interface of the singleton you just defined.

Accessing the Singleton’s Public Interface

Now that you’ve defined the singleton, you’ll add some logic so it can be accessed. To do this:

  1. Open MainActivity.kt.
  2. Find addProductToCart(), which ProductListAdapter calls when the user selects a product. That logic is already in place for you. All you need to do is replace the // TODO inside addProductToCart() with the following, importing android.widget.Toast as necessary:
ShoppingCart.addProduct(product)
Toast.makeText(
    this,
    R.string.product_added_toast, Toast.LENGTH_SHORT
).show()

Notice that you’re calling ShoppingCart.addProduct(product) by using its name.

For some visual feedback to make sure you’ve added the product successfully, you also show a Toast.

Now, build and run. Click a product and you’ll see a Toast confirming you’ve added it to the cart:

Smar-T-App screen with a list of products and a Toast notification

Next, you’ll learn how to define companion objects. You’ll use a companion object to help you launch a new activity to display the ShoppingCart contents.