From Java to Kotlin (MVVM + Retrofit + Coroutines + Jetpack)

from the CommonsWare Community archives

At September 26, 2020, 4:18pm, vedy asked:

Hi Mark,

I’m trying to convert an app from Java to Kotlin, a recipies app (RecyclerView with Recipe categories , calls an API to do recipe search , show recipes and display details of recipes), I believe the issues I’m facing are stemming from using retrofit with coroutines. specifically the use of suspend fun does not play very well with the other files in Java. But I have converted the relevant Java classes into Kotlin (using Android studio 4)
To paint a more concrete picture i’m rpoviding code snippets here:

  1. Here are the related retrofit classes
    RecipeApi
    [included in the link above] new users can only post 2 links
    RecipeApiClient.kt
    [included in the link above] new users can only post 2 links

ServiceGenerator.java
[included in the link above] new users can only post 2 links

  1. Here are the ViewModel and repo classes in Kotlin

RecipeViewModel.kt
[included in the link above] new users can only post 2 links

RecipeRepository.kt
[included in the link above] new users can only post 2 links

  1. This is how they looked like in Java

RecipeViewModel.java
[included in the link above] new users can only post 2 links

RecipeRepository.java
[included in the link above] new users can only post 2 links

  1. All seems to be well until I came across the conversion of the MainActivity, the converted Kotlin class is still giving errors related to it needs suspend function , but the MainActivity class resulting from doesn’t make sense to me.

This is the Java version of MainActivity
[included in the link above] new users can only post 2 links

and this is the Kotlin converted version
[included in the link above] new users can only post 2 links

My questions are:

Thanks in advance and let me know if you need any more details


At September 26, 2020, 5:04pm, mmurphy replied:

I am happy to try to answer specific questions that you may have regarding your code (particularly if you put the code into your question here on this site). However, I am not offering a code review service.

the converted Kotlin class is still giving errors related to it needs suspend function

searchRecipeById() in RecipeViewModel is a suspend function. It needs to be called inside of a suitable CoroutineScope or to be called by another suspend function. Your activity is doing neither.

You have two main choices:

  1. Do not expose a suspend-based API to the activity. Instead, use viewModelScope inside of your ViewModel to handle the coroutine and expose a traditional API. See https://gitlab.com/commonsguy/cw-jetpack-kotlin/-/blob/v1.1/DiceLight for an example from Elements of Android Jetpack that takes this approach.

  2. Use lifecycleScope in your activity for calling the suspend function. In https://gitlab.com/commonsguy/cw-jetpack-kotlin/-/tree/v1.1/NukeFromOrbit (from the same book), I take this approach for consuming events from a BroadcastChannel.

Do you recommend Java to Kotlin conversion using android studio at all?

The conversion works better than I would have expected, at least when I last used it (around 2 years ago). The resulting code usually compiles and frequently runs. However, for all but the simplest conversions, it usually needs some cleanup in order to become Kotlin that I would want to use long-term. For example, the converted code tends to use !! a lot, and that is a convenient yet unforgiving approach to dealing with nullable types.