Our app uses Mixpanel for analytical and strategic purposes. This post is about my refactoring journey.

Mixpanel introduced another parameter in their getInstance() method called trackAutomaticEvents which is of a boolean data type. Now, this is the part that I didn’t anticipate because located throughout our codebase is this single line.

1
MixpanelAPI.getInstance(this, Constants.MIXPANEL_TOKEN).track("Log In")

But right now it is broken since the proper way to implement on the new version is this.

1
MixpanelAPI.getInstance(this, Constants.MIXPANEL_TOKEN, true).track("Log In")

Behold them compile errors.

You might think why not use the Find All option in Android Studio? I could, but this is to future proof our codebase in case another getInstance() refactor in the future.

Kotlin Object

For the Kotlin singleton pattern, I always use object since they are good for one-time use purposes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import android.content.Context
import com.mixpanel.android.mpmetrics.MixpanelAPI

object Mixpanel {

    fun track(context: Context, track: String) {
        return MixpanelAPI.getInstance(context, Constants.MIXPANEL_TOKEN, true)
            .track(track)
    }
}

Now that I have isolated or “wrapped” in a separate class, I can now implement condition statements inside it. Most of my Mixpanel method calls were wrapped in a !isDebuggable condition and are sprinkled everywhere in our codebase. Not good.

1
2
3
4
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
if (!isDebuggable) {
     MixpanelAPI.getInstance(this@MainActivity, Constants.MIXPANEL_TOKEN).track("Session - Employer")
}

Code Refactor

Now, that I have a separate object class, I can just call the condition there instead.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import android.content.Context
import android.content.pm.ApplicationInfo
import com.mixpanel.android.mpmetrics.MixpanelAPI

object Mixpanel {

    fun track(context: Context, track: String) {
        val isDebuggable = 0 != context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
        if (!isDebuggable) {
            MixpanelAPI.getInstance(context, Constants.MIXPANEL_TOKEN, true).track(track)
        }
    }
}

So from this code block

1
2
3
4
val isDebuggable = 0 != context?.applicationInfo!!.flags and ApplicationInfo.FLAG_DEBUGGABLE
 if (!isDebuggable) {
      MixpanelAPI.getInstance(activity, Constants.MIXPANEL_TOKEN).track("Share Profile")
 }

to

1
Mixpanel.track(requireActivity(), "Share Profile")

Future Proof and Conclusion

If Mixpanel decides to update their getInstance() method, then I only have to change that one line in my object Mixpanel. This code refactor has been a long time coming. I’m just glad that I was able to push this out of the way. Now, on to the next refactor.