Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Retrofit's suspend functions with AS 4.0 and compose enabled?

I'm working on an experimental project where I'm using jetpack compose in Android Studio 4.0 and Retrofit's coroutine support.

Here is my top-level gradle.build:

buildscript {
    ext.kotlin_version = "1.3.61"
    ext.compose_version = '0.1.0-dev03'

    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.0-alpha06'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
}

task clean (type: Delete) {
    delete rootProject.buildDir
}

And here is the app module build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    defaultConfig {
        applicationId "com.example.test"
        minSdkVersion 29
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }

}


dependencies {
    def room_version = "2.2.2"
    def lifecycle_version = "2.2.0-rc03"

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.1.0'

    implementation "androidx.compose:compose-runtime:$compose_version"
    implementation "androidx.ui:ui-framework:$compose_version"
    implementation "androidx.ui:ui-layout:$compose_version"
    implementation "androidx.ui:ui-material:$compose_version"
    implementation "androidx.ui:ui-foundation:$compose_version"
    implementation "androidx.ui:ui-animation:$compose_version"
    implementation "androidx.ui:ui-tooling:$compose_version"

    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.fragment:fragment-ktx:1.2.0-rc03"

    implementation "com.squareup.retrofit2:retrofit:2.6.2"
    implementation "com.squareup.retrofit2:converter-moshi:2.4.0"
    implementation 'com.squareup.okhttp3:okhttp:4.2.1'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'
    compileOnly 'org.glassfish:javax.annotation:10.0-b28'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

And finally my problematic retrofit api service interface:

import com.example.test.data.response.SnapshotResponse
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Header

interface ApiService {
    @GET("/login")
    suspend fun login(@Header("Authorization") credentials: String): SnapshotResponse
}

Whenever I try to call this login method I get:

java.lang.IllegalArgumentException: HTTP method annotation is required (e.g., @GET, @POST, etc.) 

But when I try to change my login method to non-suspending traditional versions like this:

@GET("/login")
fun login(@Header("Authorization") credentials: String): Call<SnapshotResponse>

Then everything works fine.

This seems to be related to AS4.0's IR compiler. Did anybody found some workaround for this?

Edit: I've probably found a related issue on Retrofit's tracker https://github.com/square/retrofit/issues/3233 and google's tracker https://issuetracker.google.com/issues/143468771

like image 562
Semanticer Avatar asked Dec 10 '19 23:12

Semanticer


1 Answers

You can create a module without compose enabled where you place all your Retrofit services, it doesn't matter that the App module (that depends on your "services" module has Compose enabled as long as your "services" module doesn't have it enabled)

This workaround is working fine for me in Android Studio 4.0 canary 7.

like image 173
DanielDiSu Avatar answered Oct 07 '22 04:10

DanielDiSu