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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Object in Kotlin and the Singleton Pattern
20 mins
- Getting Started
- Using Singletons in Kotlin
- Using Object to Define a Shopping Cart Singleton
- Creating a Singleton’s Public Interface
- Accessing the Singleton’s Public Interface
- Working With Companion Objects
- Defining the Companion Object
- Accessing the Companion Object to Start the Activity
- Displaying Products in the Shopping Cart
- Accessing Kotlin Singletons with Java to Calculate Price
- Showing Products in the Shopping Cart
- Defining Object Listeners
- Listening to Cart Changes: Anonymous Objects
- Best Practices for Singletons and Companion Objects
- Where to Go From Here?
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
object
s to Java callers. - Singleton best practices.
It’s time to get started!
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.
When you open the starter project, you’ll see some structure already in place:
- MainActivity.kt: Your app’s initial screen.
- Product.kt: A model representing a product in the store.
-
ProductListAdapter.kt: A
ListAdapter
, which bothMainActivity
andShoppingCartActivity
use to populate a RecyclerView of products. - ShoppingCartActivity.kt: An activity you’ll use to display the user’s shopping cart, total price and a button to clear the cart.
-
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:
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.
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:
- To share data between two otherwise unrelated areas of your project.
- 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:
- In Android Studio, select File ▸ New ▸ Kotlin File/Class.
- In the pop-up, name your file ShoppingCart, select Object and press Enter.
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 theShoppingCart
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:
- Created a list of
Product
s. 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. - 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. - Gave the user a way to clear their shopping cart. Calling this function will empty the
products
list held byShoppingCart
.
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:
- Open MainActivity.kt.
- Find
addProductToCart()
, whichProductListAdapter
calls when the user selects a product. That logic is already in place for you. All you need to do is replace the// TODO
insideaddProductToCart()
with the following, importingandroid.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:
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.