无法为类example.Simple创建调用适配器

时间:2015-08-28 10:37:11

标签: java rest retrofit simple-framework

我正在使用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

15 个答案:

答案 0 :(得分:81)

对于 Kotlin 协程,这种情况是在我从{{1}调用此函数而忘记将api服务函数标记为suspend时发生的}:

用法:

CoroutineScope(Dispatchers.IO).launch{}

ApiService.kt

    val apiService = RetrofitFactory.makeRetrofitService()

    CoroutineScope(Dispatchers.IO).launch {

        val response = apiService.myGetRequest()

        // process response...

    }

答案 1 :(得分:52)

添加依赖项:

.site-footer {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  text-align: center;
  overflow: hidden;
  background-image: url(http://lorempixel.com/500/60);
  height: 60px;
  background-size: cover;
  background-position: center center;
}

以这种方式创建适配器:

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

答案 2 :(得分:45)

简短回答:在服务界面中返回Call<Simple>

看起来Retrofit 2.0正试图找到一种为服务接口创建代理对象的方法。它希望你写这个:

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

但是,如果您不想返回Call,它仍然希望能够发挥出色并保持灵活性。为了支持这一点,它具有CallAdapter的概念,应该知道如何将Call<Simple>调整为Simple

使用RxJavaCallAdapterFactory仅在您尝试返回rx.Observable<Simple>时才有用。

最简单的解决方案是按照Retrofit的预期返回Call。如果你确实需要,你也可以写一个CallAdapter.Factory

答案 3 :(得分:36)

使用新的Retrofit(2. +),您需要添加addCallAdapterFactory(可以是普通的)或RxJavaCallAdapterFactory(对于Observables)。我认为你可以添加更多。它会自动检查使用哪一个。请参阅下面的工作示例。您还可以查看this link了解详情。

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

答案 4 :(得分:14)

如果您想使用retrofit2并且不想总是返回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);
}

答案 5 :(得分:13)

为改装2添加以下依赖关系

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

对于GSON

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

for observables

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);

答案 6 :(得分:4)

在我的情况下使用此

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

用这个

new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
当没有其他工作时,

解决了问题

答案 7 :(得分:1)

只是让那些正在迁移,不使用Rx或者想要同步调用的人更清楚地调用Call示例 - Call基本上替换(换行)Response,意思是:

Response<MyObject> createRecord(...);

成为

Call<MyObject> createRecord(...);

而不是

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

(仍然需要适配器)

然后,调用将允许您仍然使用isSuccessful,因为它实际返回响应。所以你可以这样做:

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

或者访问您的Type(MyObject),如:

MyObject myObj = myApi.createRecord(...).execute().body();

答案 8 :(得分:1)

如果您不使用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)

答案 9 :(得分: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
    }

}

答案 10 :(得分:0)

val navigationButton = ...
navigationButton.setOnClickListener {
  val drawerlayout = requireActivity().findViewById<DrawerLayout>(
    R.id.main_drawer_layout)
  drawerLayout.openDrawer(GravityCompat.START)
}

与网络的通信是通过单独的线程完成的,因此您应使用该线程更改简单。

public interface SimpleService {

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

}

答案 11 :(得分:0)

我使用的是

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

代替

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

使用com.squareup.retrofit2:adapter-rxjava2:2.5.0时应该使用io.reactivex.rxjava2

答案 12 :(得分:0)

IllegalArgumentException:无法为类java.lang.Object创建调用适配器

简短的回答:我已经通过以下更改解决了

~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in _assert_all_finite(X, allow_nan)
     58     elif X.dtype == np.dtype('object') and not allow_nan:
     59         if _object_dtype_isnan(X).any():
---> 60             raise ValueError("Input contains NaN")
     61 
     62 

ValueError: Input contains NaN\

祝你好运

答案 13 :(得分:0)

我找到了一个解决方案,在我的情况下,我使用来自 JAVA 的 ApiInterface.java 连接来自 KOTLIN 的 MyViewModel.kt

  1. 这是ApiInterface.java

    @GET(Constant.CONNECTION) 调用 ConnectionKt();

  2. 您需要创建一个新的 Kotlin 类,命名为 ApiTemporary.kt

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

    暂停乐趣 getConnectionKt(): Response { 返回 apiInterface.ConnectionKt().awaitResponse() } }

  3. 最后,在MyViewModel.kt,你可以这样做

val 数据 = withContext(ioDispatcher) { val 结果 = apiTemporary.getConnectionKt() 如果(result.isSuccessful){ Resource.Success(result.body()) } 别的 { Resource.Error("服务器错误,请重试") } } _connection.value = 数据

因此,ApiTemporary 将有助于将它们从 Java 转换为 Kotlin,这是协程的用法

答案 14 :(得分:-2)

我修复此问题的方法是将其添加到应用程序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();

希望它有所帮助!