Intro to Android Development
  • Welcome
  • Syllabus
  • Hack Challenge
  • Resources
    • Lecture Videos
    • Ed Discussion
    • Git & GitHub Help/How-To
    • Setting up Android Studio
    • Starting an Android Studio Project & Making an Emulator
    • Importing, Exporting, & Submitting Your Projects to CMS
  • SP25 Course Material
    • Week 1 | Course Logistics, Kotlin, & Basic UI
      • Relevant Links
      • Demo/Lecture: Eatery Card
      • A0: Eatery Card (Follow-Along)
    • Week 2 | States, Components, LazyColumn
      • Relevant Links
      • Demo: Todo List
      • A2: Shopping List
    • Week 3 | Navigation & Animations
      • Relevant Links
      • Demo: Onboarding
      • A3: Stock Trading (RobbingGood)
    • Week 4 | MVVM and Flows
      • Relevant Links
      • Demo: Eatery Card 2
      • A4: Chat of a Lifetime
    • Week 5 | Dumb Components & UIEvents
      • Relevant Links
      • Demo: Music Player
      • A5: Rate My Vibe
    • Week 6 | Coroutines, Networking, JSON
      • Relevant Links
      • Demo: Retrofit
      • A6: You Should Even Lift, Bro.
  • Bonus Week | Android Job Search
    • Relevant Links
    • Android Technical Interview Question!
  • Textbook
    • 1. Introduction to the Editor and Views
      • 1.1 Introduction to the Editor
      • 1.2 SDK Management
      • 1.3 Kotlin Overview
      • 1.4 Views
      • 1.5 Android Studio Project Demo + Understanding The Editor
    • 2. Jetpack Compose
      • 2.1 Introduction
      • 2.2 Layouts
      • 2.3 Modifiers
      • 2.4 Animations
      • 2.5 Lazy Lists
      • 2.6 Reactive UI
    • 3. Intents and Manifest
      • 3.1 Activities
      • 3.2 Implicit Intents
      • 3.3 Explicit Intents
      • 3.4 Manifest
      • 3.5 Permissions
      • 3.6 Summary
    • 4. Navigation
      • 4.1 Types of Navigation
      • 4.2 Implementation of the Bottom Navigation Bar
    • 5. Data and Persistent Storage
      • 5.1 Singleton Classes
      • 5.2 Shared Preferences
      • 5.3 Rooms
      • 5.4 Entities
      • 5.5 Data Access Objects
      • 5.6 Databases
    • 5.5 Concurrency
      • 5.5.1 Coroutines
      • 5.5.2 Implementation of Coroutines
      • 5.5.3 Coroutines with Networking Calls
    • 6. Networking and 3rd Party libraries
      • 6.1 HTTP Overview
      • 6.2 3rd Party Libraries
      • 6.3 JSON and Moshi
      • 6.4 Retrofit
      • 6.5 Summary
    • 7. MVVM Design Pattern
      • 7.1 Key Idea
      • 7.2 Implementation Ideas
    • 8. Flows
    • 9. The Art and Ontology of Software
    • 10. 🔥 Firebase
      • 10.1 Setting up Firebase
      • 10.2 Authentication
      • 10.3 Analytics
      • 10.4 Messaging
      • 10.5 Firestore
  • Additional Topics
    • Git and GitHub
    • Exporting to APK
  • Archive
    • Archived Native Android Textbook Pages
      • 1. Layouts and More Views
        • 1.1 File Structure and File Types
        • 1.2 Resource Files
        • 1.3 Button and Input Control
        • 1.4 ViewGroups
        • 1.5 Summary + A Note On Chapter 2 Topics
      • 2. RecyclerViews
        • 2.1 RecyclerViews
        • 2.2 RecyclerView Performance
        • 2.3 Implementation of a Recycler View
        • 2.4 Implementation with Input Controls
        • 2.5 Filtering RecyclerViews
        • 2.6 Recyclerview Demo
      • 3. ListViews and Searching
        • 3.1 ListView vs. RecyclerView
        • 3.2 ListView Performance
        • 3.3 Implementation of a ListView
        • 3.4 Searching in a List View
      • 4. Fragments
        • 4.1 What are Fragments?
        • 4.2 Lifecycle of a Fragment
        • 4.3 Integrating a Fragment into an Activity
        • 4.4 Sharing Data Between Fragments
        • 4.5 Fragment Slide Shows
      • 5. OkHttp
      • 6. Activity Lifecycle
      • 7. Implementation of Tab Layout
    • Fall 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 1.5: Beauty of Kotlin
      • Lecture 2 & HW 2: Modifiers, Lazylists and Reactive UI
      • Lecture 3 & HW 3: Animations, Intents and Manifest
      • Lecture 4 & HW 4: Coroutines & Navigation
      • Lecture 5 & HW 5: Persistent Storage, Networking, and JSON Parsing
      • Lecture 6 & HW 6: MVVM, Flows
      • Bonus Lectures & Bonus HW
      • Bonus Lecture: Industry Practice
    • Spring 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 4 & HW 4: LazyLists
      • Lecture 6 & HW 6: Networking, Data, and Persistent Storage
    • Spring 2020 Course Material
      • Week 1: Intro to the Editor
      • Week 2: Views and Layouts
      • Week 3: Intent and Manifest
      • Week 4: ListView and RecyclerView
      • Week 5: Fragments
      • Week 6: Networking
    • Spring 2021 Lecture & HW 8: Networking & 3rd Party APIs
    • HackOurCampus Workshop
Powered by GitBook
On this page
  • Singleton Class Attributes:
  • Rules for making a class Singleton
  • Implementation

Was this helpful?

  1. Textbook
  2. 5. Data and Persistent Storage

5.1 Singleton Classes

A singleton is a design pattern that restricts the instantation of a class to only one instance; a singleton class is a class that is defined in such a way that only one instance of the class can be created and used everywhere.

This is used when creating a central point of access for an application to access its data store. In Android this is very conveinient as many times we need an application to be able to access a central in-sync data store location from across many differant activities or fragments.

Singleton Class Attributes:

  1. Only one instance: The singleton class has only one instance. Also, outer classes and subclasses should be prevented to create the instance.

  2. Globally accessible: The instance of the singleton class should be globally accessible so that each class can use it.

Rules for making a class Singleton

The following rules are followed to make a Singleton class:

  1. A private constructor

  2. Globally accessible object reference

  3. Consistency across multiple threads

Implementation

We can leverage using the object keyword. In Kotlin, object is a special class that only has one instance. If you create a class with the object keyword instead of class, the Kotlin compiler makes the constructor private, creates a static reference for the object, and initializes the reference in a static block, automatically fulfilling the singleton contract.

Contrary to a class, an object can’t have any constructor, but init blocks are allowed if some initialization code is needed.

Here's an example singleton of a simple counter:

object Counter {
    var counter: Int
        // Only allows retrival of the counter, 
        // setting restricted to only within Singleton
        private set
    
    // Optional init block if you need some initalization
    init {
        counter = 0
    }

    // Increments the counter and returns the new number after incrementing.
    fun incrementCounter(): Int {
        return ++counter
    }
    
    // Can define whatever member functions you want!
}

Now, the singleton can be easily invoked by writing the below code:

val counter = Counter
counter.incrementCounter()

object comes with a limitation: object declarations can not have constructors which means they can not take parameters.

What if we want to take in arguments?

We can leverage companion object to create a singleton class! In short, companion objects are singleton objects whose properties and functions are tied to a class but not to the instance of that class — basically like the “static” keyword in Java but with a twist.

Here's the equivalent object as a singleton class:

class Counter private constructor(private var counter: Int) {   
    fun incrementCounter(): Int {
        return this.counter++
    }
    
    // The only way to instantiate Counter is through our companion object!
    companion object {
        private var instance: Counter? = null
        
        // Use of synchronized helps prevent race conditions (which you may know
        // what this is if you've taken an operating systems class, if not don't
        // worry too much!)
        fun getInstance(param: Int): Counter = instance ?: synchronized(this) {
            instance ?: Counter(param).also { instance = it }
        }
    }
}

Key things to note:

  • Make sure that your constructor is private

  • Add any data you are interested in as an argument to the constructor, expand the definition of getInstance if so.

Now, the singleton can be easily invoked by writing the below code:

val counter = Counter.getInstance(0)
counter.incrementCounter()
Previous5. Data and Persistent StorageNext5.2 Shared Preferences

Last updated 7 months ago

Was this helpful?