How to create a call adapter for suspending functions in Retrofit? : <p>I need to create a retrofit call adapter which can handle such network calls:</p>

<pre><code>@GET("user")
suspend fun getUser(): MyResponseWrapper&lt;User&gt;
</code></pre>

<p>I want it to work with Kotlin Coroutines without using <code>Deferred</code>. I have already have a successful implementation using <code>Deferred</code>, which can handle methods such as:</p>

<pre><code>@GET("user")
fun getUser(): Deferred&lt;MyResponseWrapper&lt;User&gt;&gt;
</code></pre>

<p>But I want the ability make the function a suspending function and remove the <code>Deferred</code> wrapper.</p>

<p>With suspending functions, Retrofit works as if there is a <code>Call</code> wrapper around the return type, so <code>suspend fun getUser(): User</code> is treated as <code>fun getUser(): Call&lt;User&gt;</code></p>

<h3>My Implementation</h3>

<p>I have tried to create a call adapter which tries to handle this. Here is my implementation so far:</p>

<p><strong>Factory</strong></p>

<pre><code>class MyWrapperAdapterFactory : CallAdapter.Factory() {

    override fun get(returnType: Type, annotations: Array&lt;Annotation&gt;, retrofit: Retrofit): CallAdapter&lt;*, *&gt;? {

        val rawType = getRawType(returnType)

        if (rawType == Call::class.java) {

            returnType as? ParameterizedType
                ?: throw IllegalStateException("$returnType must be parameterized")

            val containerType = getParameterUpperBound(0, returnType)

            if (getRawType(containerType) != MyWrapper::class.java) {
                return null
            }

            containerType as? ParameterizedType
                ?: throw IllegalStateException("MyWrapper must be parameterized")

            val successBodyType = getParameterUpperBound(0, containerType)
            val errorBodyType = getParameterUpperBound(1, containerType)

            val errorBodyConverter = retrofit.nextResponseBodyConverter&lt;Any&gt;(
                null,
                errorBodyType,
                annotations
            )

            return MyWrapperAdapter&lt;Any, Any&gt;(successBodyType, errorBodyConverter)
        }
        return null
    }
</code></pre>

<p><strong>Adapter</strong></p>

<pre><code>class MyWrapperAdapter&lt;T : Any&gt;(
    private val successBodyType: Type
) : CallAdapter&lt;T, MyWrapper&lt;T&gt;&gt; {

    override fun adapt(call: Call&lt;T&gt;): MyWrapper&lt;T&gt; {
        return try {
            call.execute().toMyWrapper&lt;T&gt;()
        } catch (e: IOException) {
            e.toNetworkErrorWrapper()
        }
    }

    override fun responseType(): Type = successBodyType
}
</code></pre>

<pre><code>runBlocking {
  val user: MyWrapper&lt;User&gt; = service.getUser()
}
</code></pre>

<p>Everything works as expected using this implementation, but just before the result of the network call is delivered to the <code>user</code> variable, I get the following error:</p>

<pre><code>java.lang.ClassCastException: com.myproject.MyWrapper cannot be cast to retrofit2.Call

    at retrofit2.HttpServiceMethod$SuspendForBody.adapt(HttpServiceMethod.java:185)
    at retrofit2.HttpServiceMethod.invoke(HttpServiceMethod.java:132)
    at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
    at com.sun.proxy.$Proxy6.getText(Unknown Source)
    ...
</code></pre>

<p>From Retrofit's source, here is the piece of code at <code>HttpServiceMethod.java:185</code>:</p>

<pre class="lang-java prettyprint-override"><code>    @Override protected Object adapt(Call&lt;ResponseT&gt; call, Object[] args) {
      call = callAdapter.adapt(call); // ERROR OCCURS HERE

      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation&lt;ResponseT&gt; continuation = (Continuation&lt;ResponseT&gt;) args[args.length - 1];
      return isNullable
          ? KotlinExtensions.awaitNullable(call, continuation)
          : KotlinExtensions.await(call, continuation);
    }
</code></pre>

<p>I'm not sure how to handle this error. Is there a way to fix?</p>
