Scoping Retrofit calls to Activity/Fragment in Android

Kirtan Thakkar

Kirtan Thakkar

Life is all about learning

I have had a tough time managing retrofit calls on android while making a REST calls to display something on UI. When the activity/fragment is destroyed you don't need the result anymore. You simply need to cancel that call else it may leak your activity.

To tackle this situation, what I essentially found is, hold a reference to the retrofit's Call object and cancel it on Activity's onDestroy. It may sound good until you have 1 or 2 (or 3) calls. But, what if you have multiple REST calls and all going on here and there, making it a bit difficult to manage.

I will use Kotlin to show examples. Yes, I am a kotlin fan!

override fun onDestroy() {
super.onDestroy()
mCall.cancel()
}

So, basically this makes my code ugly. And I found there was no easy way to get around it. Until, I found one. Yay!

After spending some time to understand the new Android Architecture Components and lifecycle methods, I found a way. Kotlin's extension functions comes to the rescue here. I decided to scope a call to given Activity (or Fragment).

So, I created an extension function of Retrofit's Call<T> and made a function named enqueue which excepts 2 arguments.

  1. Scope: Activity/Fragment -- or anything which implements LifecycleOwner
  2. Callback: Which standard retrofit call has.

Now, I needed some kind of callback, from the activity which can tell me, "I am finished, do you want to do something?"! With the new support library, I can do this. AppCompatActivity and support Fragment implements LifecycleOwner. This makes the job easy. Let's attach a listener to it and cancel the call. Let's see it in action:

fun <T> Call<T>.enqueue(lifecycleOwner: LifecycleOwner, callback: Callback<T>) {
// add an observer to activity which will cancel an ongoing call
// when activity is destroyed
lifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun cancelCalls() {
}
})
this.enqueue(callback)
}

Magic! Isn't it? ;)

This is super simple to call. Just call a normal enqueue method with callback and pass an extra first argument with the activity/fragment. This function will handle the rest and makes the job easy for you.

call.enqueue(this@MainActivity, Callback { /* my callback */})

As this is super useful, I have added this to my library K4Kotlin and readily available for you to use. It has also some other Retrofit helpers which will make writing code fun again. Try it out and let me know about it.

Happy coding! #BuildBetterApps