簡體   English   中英

無法為類示例創建調用適配器。簡單

[英]Unable to create call adapter for class example.Simple

我正在使用帶有 SimpleXml 的改造 2.0.0-beta1。 我想要從 REST 服務中檢索簡單 (XML) 資源。 使用 SimpleXML 編組/解組 Simple 對象可以正常工作。

使用此代碼時(轉換為 2.0.0 之前的代碼):

final Retrofit rest = new Retrofit.Builder()
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .baseUrl(endpoint)
    .build();
SimpleService service = rest.create(SimpleService.class);
LOG.info(service.getSimple("572642"));

服務:

public interface SimpleService {

    @GET("/simple/{id}")
    Simple getSimple(@Path("id") String id);

}

我得到這個例外:

Exception in thread "main" java.lang.IllegalArgumentException: Unable to create call adapter for class example.Simple
    for method SimpleService.getSimple
    at retrofit.Utils.methodError(Utils.java:201)
    at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:51)
    at retrofit.MethodHandler.create(MethodHandler.java:30)
    at retrofit.Retrofit.loadMethodHandler(Retrofit.java:138)
    at retrofit.Retrofit$1.invoke(Retrofit.java:127)
    at com.sun.proxy.$Proxy0.getSimple(Unknown Source)

我錯過了什么? 我知道通過Call包裝返回類型是可行的。 但我希望服務將業務對象作為類型返回(並在同步模式下工作)。

更新

按照不同答案的建議添加額外的依賴項和.addCallAdapterFactory(RxJavaCallAdapterFactory.create())后,我仍然收到此錯誤:

Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
 * retrofit.RxJavaCallAdapterFactory
 * retrofit.DefaultCallAdapter$1

Kotlin協程的情況下,當我從CoroutineScope(Dispatchers.IO).launch{}調用此函數時忘記將 api 服務函數標記為suspend時,就會發生這種情況:

用法:

    val apiService = RetrofitFactory.makeRetrofitService()

    CoroutineScope(Dispatchers.IO).launch {

        val response = apiService.myGetRequest()

        // process response...

    }

ApiService.kt

interface ApiService {

       @GET("/my-get-request")
       suspend fun myGetRequest(): Response<String>
}

簡短的回答:在您的服務界面中返回Call<Simple>

看起來 Retrofit 2.0 正在嘗試找到一種為您的服務接口創建代理對象的方法。 它希望你這樣寫:

public interface SimpleService {
    @GET("/simple/{id}")
    Call<Simple> getSimple(@Path("id") String id);
}

但是,當您不想返回Call時,它仍然希望表現得很好並且靈活。 為了支持這一點,它具有CallAdapter的概念,它應該知道如何將Call<Simple>調整為Simple

僅當您嘗試返回rx.Observable<Simple>時,使用RxJavaCallAdapterFactory才有用。

最簡單的解決方案是按照 Retrofit 的預期返回一個Call 如果你真的需要,你也可以寫一個CallAdapter.Factory

添加依賴項:

compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'

以這種方式創建您的適配器:

Retrofit rest = new Retrofit.Builder()
    .baseUrl(endpoint)
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .build();

addCallAdapterFactory ()addConverterFactory ()都需要調用。

服務:

public interface SimpleService {

    @GET("/simple/{id}")
    Call<Simple> getSimple(@Path("id") String id);

}

Simple修改為Call<Simple>

使用新的 Retrofit(2.+),您需要添加 addCallAdapterFactory,它可以是普通的,也可以是 RxJavaCallAdapterFactory(用於 Observables)。 我認為您也可以添加更多內容。 它會自動檢查要使用哪一個。 請參閱下面的工作示例。 您還可以查看此鏈接以獲取更多詳細信息。

 Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build()

如果你想使用retrofit2並且你不想總是返回 retrofit2.Call retrofit2.Call<T> ,你必須創建你自己的CallAdapter.Factory ,它返回你所期望的簡單類型。 簡單的代碼如下所示:

import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

public class SynchronousCallAdapterFactory extends CallAdapter.Factory {
    public static CallAdapter.Factory create() {
        return new SynchronousCallAdapterFactory();
    }

    @Override
    public CallAdapter<Object, Object> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
        // if returnType is retrofit2.Call, do nothing
        if (returnType.toString().contains("retrofit2.Call")) {
            return null;
        }

        return new CallAdapter<Object, Object>() {
            @Override
            public Type responseType() {
                return returnType;
            }

            @Override
            public Object adapt(Call<Object> call) {
                try {
                    return call.execute().body();
                } catch (Exception e) {
                    throw new RuntimeException(e); // do something better
                }
            }
        };
    }
}

然后簡單地在 Retrofit 中注冊SynchronousCallAdapterFactory應該可以解決您的問題。

Retrofit rest = new Retrofit.Builder()
        .baseUrl(endpoint)
        .addConverterFactory(SimpleXmlConverterFactory.create())
        .addCallAdapterFactory(SynchronousCallAdapterFactory.create())
        .build();

之后,您可以在沒有retrofit2.Call的情況下返回簡單類型。

public interface SimpleService {
    @GET("/simple/{id}")
    Simple getSimple(@Path("id") String id);
}

為改造 2 添加以下依賴項

 compile 'com.squareup.retrofit2:retrofit:2.1.0'

用於 GSON

 compile 'com.squareup.retrofit2:converter-gson:2.1.0'

對於可觀察的

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

對於 XML ,您必須包含以下依賴項

 compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'

更新服務調用如下

final Retrofit rest = new Retrofit.Builder()
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .baseUrl(endpoint)
    .build();
SimpleService service = rest.create(SimpleService.class);

IllegalArgumentException:無法為類 java.lang.Object 創建調用適配器

簡短回答:我通過以下更改解決了它

ext.retrofit2Version = '2.4.0' -> '2.6.0'
implementation"com.squareup.retrofit2:retrofit:$retrofit2Version"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"

祝你好運

對於這種情況:

val apiService = RetrofitFactory.makeRetrofitService()

CoroutineScope(Dispatchers.IO).launch {

    val response = apiService.myGetRequest()

    // process response...

}

interface ApiService {

   @GET("/my-get-request")
   suspend fun myGetRequest(): Response<String>
}

suspend函數中使用的所有方法都必須標記為suspend ,因為它是由 Corountine 管理的。 在這里查看更多信息。

因此,如果您在 CoroutineScope 或任何suspend標記的方法中調用 API 服務函數時未將其標記為suspend ,則 android 應用程序會崩潰並Exception in thread "main" java.lang.IllegalArgumentException: Unable to create call adapter for class example.class錯誤。

在我的情況下使用這個

compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

有了這個

new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...

當沒有其他工作時解決了問題

如果你沒有使用 RxJava,那么僅僅為了改造而添加 RxJava 是沒有意義的。 2.5.0支持內置的CompletableFuture ,您可以在不添加任何其他庫或適配器的情況下使用它。

build.gradle.kts

implementation("com.squareup.retrofit2:retrofit:2.5.0")
implementation("com.squareup.retrofit2:retrofit-converters:2.5.0")

Api.kt

interface Api {
    @GET("/resource")
    fun listCompanies(): CompletableFuture<ResourceDto>
}

用法:

Retrofit.Builder()
   .addConverterFactory(SimpleXmlConverterFactory.create())
   .baseUrl("https://api.example.com")
   .build()
   .create(Api::class.java)

我將 Coroutines 與CoroutineCallAdapterFactory一起使用,但不小心忘記了使函數suspend 希望它可以幫助某人!

只是為了讓遷移、不使用 Rx 或想要同步調用的人更清楚調用示例 - 調用本質上替換(包裝)響應,這意味着:

Response<MyObject> createRecord(...);

變成

Call<MyObject> createRecord(...);

並不是

Call<Response<MyObject>> createRecord(...);

(仍然需要適配器)


然后,調用將允許您仍然使用isSuccessful ,因為它實際上返回一個響應。 因此,您可以執行以下操作:

myApi.createRecord(...).execute().isSuccessful()

或訪問您的類型(MyObject),如:

MyObject myObj = myApi.createRecord(...).execute().body();
public interface SimpleService {

  @GET("/simple/{id}")
  Simple getSimple(@Path("id") String id);

}

與網絡的通信是通過單獨的線程完成的,所以你應該用它來改變你的 Simple 。

public interface SimpleService {

  @GET("/simple/{id}")
  Call<Simple> getSimple(@Path("id") String id);

}

在我的情況下,我使用

com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava

代替

com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2

使用 io.reactivex.rxjava2 時,您應該使用io.reactivex.rxjava2 com.squareup.retrofit2:adapter-rxjava2:2.5.0

您可以實現一個回調,從 onResponse 函數中獲取 Simple。

public class MainActivity extends Activity implements Callback<Simple> {

    protected void onCreate(Bundle savedInstanceState) {
        final Retrofit rest = new Retrofit.Builder()
                    .addConverterFactory(SimpleXmlConverterFactory.create())
                    .baseUrl(endpoint)
                    .build();
        SimpleService service = rest.create(SimpleService.class);
        Call<Simple> call = service.getSimple("572642");
        //asynchronous call
        call.enqueue(this);

        return true;
    }

    @Override
    public void onResponse(Response<Simple> response, Retrofit retrofit) {
       // response.body() has the return object(s)
    }

    @Override
    public void onFailure(Throwable t) {
        // do something
    }

}

我找到了一個解決方案,在我的情況下,我使用來自 JAVA 的ApiInterface.java來連接來自MyViewModel.kt的 MyViewModel.kt。

  1. 這是ApiInterface.java

    @GET(Constant.CONNECTION) 調用<com.example.kt.model.ConnectionResponse> ConnectionKt();

  2. 您需要創建一個新的 Kotlin 類,命名為ApiTemporary.kt

    類 ApiTemporary(私有 val apiInterface:ApiInterface = RetrofitClient.getRetrofitInstance().create(ApiInterface::class.java)){

    暫停樂趣 getConnectionKt(): Response { return apiInterface.ConnectionKt().awaitResponse() } }

  3. 所以最后,在MyViewModel.kt ,你可以這樣做

val data = withContext(ioDispatcher) { val result = apiTemporary.getConnectionKt() if (result.isSuccessful) { Resource.Success(result.body()) } else { Resource.Error("服務器錯誤。請重試") } } _connection.value = 數據

因此, ApiTemporary將有助於將它們從 Java 轉換為 Kotlin,這是協程的使用

我通過在 gradle 中將改造版本更新到 2.9.0 來解決

如果您的 API 接口返回 Response 對象,那么您可能忘記在 API 接口中添加掛起功能。

API接口

interface WeatherAPI {
    @GET("/data/2.5/weather")
    suspend fun getWeatherInfo(
        @Query("q") query: String
    ): Response<WeatherResponse>
}

存儲庫

class WeatherRepositoryImpl @Inject constructor(
private val weatherAPI: WeatherAPI
) : WeatherRepository {
    override suspend fun getWeatherInfo(query: String): Resource<WeatherResponse> {
        try {
            val response = weatherAPI.getWeatherInfo(query)
            if (response.isSuccessful) {
                response.body()?.let {
                    return Resource.success(it)
                } ?: return Resource.error("Unknown error occurred", null)
            } else {
                return Resource.error("Unknown error occured", null)
            }
        } catch (e: Exception) {
            return Resource.error("Please check your internet connection", null)
        }
    }

}

我解決這個問題的方法是將這個添加到應用程序的 gradle 文件中,如果沒有設置配置會有沖突,也許這將在庫的穩定版本中修復:

configurations {
    compile.exclude group: 'stax'
    compile.exclude group: 'xpp3'
}

dependencies {
    compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
    compile 'com.squareup.retrofit:converter-simplexml:2.0.0-beta1'
}

並以這種方式創建您的適配器:

  Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(endPoint)
            .addConverterFactory(SimpleXmlConverterFactory.create())
            .build();

希望能幫助到你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM