0
votes

I am running into some issues regarding generics, recursion and inline reified.

First, I want to recursively call a method that uses generics. This method makes request calls from a stack of requests. Lets say 5 requests need to be made, where 4 are done under the hood and only the last one is important. The others are sanity checks.

private fun <T : EmptyStateInfo> multipleRequests(
        callback: Callback<T>?
) {

    ...
    // request is made here. On the success of that request, this method is called again to make another request. I use a linkedList of requests to keep track.
}

Now that the sanity check requests are made and successful, the last request I would like to bubble up the response (or error) to the presentation layer. The problem I am facing is that the method for processing the response is inline reified. I am unable to call this method without receiving the error, "cannot use T as a reified type parameter".

private inline fun <reified T : EmptyStateInfo> handleResponse(
        response: Response,
        callback: Callback<T>?
) = when (response) {
    is Response.StringResponseItem -> {
        try {
            val responseData = gson.fromJson(response.data, T::class.java)
            ...
            // do something with response data
        } catch (e: JsonSyntaxException) {
            handleNonHttpFailure(e, callback)
        }
    }
}

How to solve this issue? Here is what I have tried.

  1. Remove inline reified from handleResponse() : I am unable to make handleResponse() not be inline reified because of the use of T::class.java. I won't be able to use T in that manner if I do that.
  2. Make multipleRequests() reified : Doing this allows me to call handleResponse() just fine, however, I am unable to recursively call multipleRequests(). I get back error that says

inline function 'private final inline fun multipleRequests()' cannot be recursive

Anyone with any ideas on how to approach this problem?

1

1 Answers

2
votes

You don't really need reified T in your handleResponse method, neither you want to inline it as you're generating ton of trash bytecode.

What you can do is have inlined method overload which pulls class out of reified parameter and calls normal method which can be called recursively without issue:

// reified entry point
private inline fun <reified T : EmptyStateInfo> multipleRequests(callback: Callback<T>?) = multipleRequests(callback, T::class.java)

// recursive method
private fun <T : EmptyStateInfo> multipleRequests(callback: Callback<T>?, tClass : Class<T>) {
    // ... calls requests passing tClass as argument
}

private fun <T : EmptyStateInfo> handleResponse(
    response: Response,
    callback: Callback<T>?,
    tClass : Class<T>){
    // ... something something
    val responseData = gson.fromJson(response.data, tClass)
    // ... etc
}