Curious case with Fragment’s onCreateAnimation()

What will happen if you override a method from a parent class and within this overriden method simply call super ‘s implementation?

The overriden method won’t introduce any issues and the behavior of the class won’t get changed — I bet you think just the way as I though.

You wouldn’t see this post if that was the case. Consider a simple fragment class with following implementation:

class MyFragment : Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.my_fragment, container, false)
}

}

Adding this fragment into activity will work as expected. Now consider exactly this fragment, just with one method overriden:

class MyFragment : Fragment() {
  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.my_fragment, container, false)
}
  override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation {
return super.onCreateAnimation(transit, enter, nextAnim)
}
}

Will this fragment get displayed? Not only it will not, but the app will crash 💥

What do we have in stacktraces?

super.onCreateAnimation(transit, enter, nextAnim) must not be null

Not super helpful stacktrace, is it?

At this point you should think “ok, if super.onCreateAnimation() must not be null, how the hell did it work back when I haven’t overriden that method??”

Let me debug this sh**

It’s the FragmentManagerImpl which calls fragment.onCreateAnimation(transit, enter, nextAnim) :

But, as you can see in the video, the executions jumps to an unknown piece of code after executing super implementation.

Neither stacktrace, nor debugging gave any valuable information. Are we stuck? In fact I was…for a moment.

Then I tried to reproduce the issue using a Java code. Guess what? No crash happened, the code just worked.

So, the problem is with Kotlin code. What might the issue be connected with? We are somehow dealing with null/non-null issue here…

A-HA!!

Turns out it’s literally one-symbol absence issue. I think you already guessed which one…

The problem is that Android Studio’s autocompletion generated a code for us, which promised to return an Animation , which in Kotlin language is a promise not to be null. But, turns out, we violate this promise and return null on runtime.

Simply adding a question mark to the return value (thus making it nullable) will make the code run as expected:

override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
return super.onCreateAnimation(transit, enter, nextAnim)
}

It’s a pity, that compiler doesn’t take care of providing a meaningful error message.

TL;DR

When overriding a method that is declared in Java make sure that parameters are correctly declared in Kotlin part, otherwise you’d end up in an untrackable issue.

Thanks for reading. Subscribe and happy droding! 🤖