Byte 3 – Kotlin delegations & analytics
Some time ago, a tweet caught my attention in which someone said they created an Android app with no “Base” activity/fragment class. Looking at my apps, I thought that was impossible to do because of the duplicate code you would have. It would have been a nightmare even only for the analytics functions that I use throughout the app.
But that got me started thinking, so I spent some time doing some research on how I could achieve this and if it would be worth doing. While doing some digging I discovered that Kotlin has delegations and we can move part of the logic of a class to an interface.
Code time
My BaseActivity starts off like this:
1 2 3 4 5 6 7 8 9 10 11 |
abstract class ClassOne { private lateinit var firebaseInstance: FirebaseAnalytics override fun onCreate(...) { firebaseInstance = FirebaseAnalytics.getInstance(this) } fun logEvent(eventName: String) { firebaseInstance.logEvent(eventName, null) } } |
Now let’s create an interface and add the initialize
and the logEvent
function to it:
1 2 3 4 |
interface Analytics { fun setUpAnalytics(activity: BaseActivity) fun logEvent(eventName: String) } |
Now we create a delegate for the interface and move the actual logic from the activity
1 2 3 4 5 6 7 8 9 10 11 12 |
class AnalyticsDelegation: Analytics { private lateinit var firebaseInstance: FirebaseAnalytics override fun setUpAnalytics(activity: Activity) { firebaseInstance = FirebaseAnalytics.getInstance(activity) } override fun logEvent(eventName: String) { firebaseInstance.logEvent(eventName, null) } } |
Now we will implement the interface in our activity and use the by
keyword to actually delegate the logic of the interface.
1 2 3 4 5 6 7 |
class MyActivity : AppCompatActivity(), Analytics by AnalyticsDelegation() { override fun onCreate(...) { setUpAnalytics(this) } } |
Why use delegation?
We shouldn’t use delegates just because it’s the new shiny and cool thing, we should use it cause it solves a problem, for me the problems were:
- It lets me favor composition over inheritance.
- I can separate my logic way better: analytics, UI behavior, feature toggles, or any other common logic.
- We can override a subset of an object’s behaviors
Final take
What I don’t like with this approach is that we still have to call setUpAnalytics in every activity, but luckily android is migrating more and more to a single activity architecture so that won’t really be a problem.
Another solution to the above problem would be having a singleton abstraction wrapper over the analytics library, but the downside of it being a singleton is that it can’t be properly tested.
Given all of this, I will still use a BaseActivity, but will definitely move most of the logic to an interface delegate.
By: Adrian Coman