Real World Example

Analytics Tracker Singleton

Example

Apps send events (screen views, purchases) through one shared tracker that batches them before upload.

object Analytics {
    private const val BATCH_SIZE = 3
    private val queue = mutableListOf<String>()
    private var batchNo = 0

    fun track(event: String, vararg params: Pair<String, Any>) {
        queue += event + params.joinToString(prefix = "{", postfix = "}") { "${it.first}=${it.second}" }
        if (queue.size >= BATCH_SIZE) flush()
    }

    fun flush() {
        if (queue.isEmpty()) return
        batchNo++
        println("Uploading batch $batchNo: $queue")
        queue.clear()
    }
}

fun main() {
    Analytics.track("screen_view", "name" to "home")
    Analytics.track("search", "query" to "running shoes")
    Analytics.track("add_to_cart", "sku" to "NK-221", "price" to 3499)
    Analytics.track("checkout_start")
    Analytics.flush()
}

Output

Uploading batch 1: [screen_view{name=home}, search{query=running shoes}, add_to_cart{sku=NK-221, price=3499}]
Uploading batch 2: [checkout_start{}]

Android: Fragment newInstance and Constants

Android code uses companion objects for intent keys, newInstance() factories and tags.

class ProductDetailFragment : Fragment(R.layout.fragment_product_detail) {

    companion object {
        private const val ARG_PRODUCT_ID = "product_id"
        const val TAG = "ProductDetail"

        fun newInstance(productId: Long) = ProductDetailFragment().apply {
            arguments = bundleOf(ARG_PRODUCT_ID to productId)
        }
    }

    private val productId by lazy { requireArguments().getLong(ARG_PRODUCT_ID) }
}

// Usage
supportFragmentManager.commit {
    replace(R.id.container, ProductDetailFragment.newInstance(42L), ProductDetailFragment.TAG)
}