我正在使用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
答案 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
。
这是ApiInterface.java
@GET(Constant.CONNECTION)
调用
您需要创建一个新的 Kotlin 类,命名为 ApiTemporary.kt
类 ApiTemporary( 私有 val apiInterface: ApiInterface = RetrofitClient.getRetrofitInstance().create(ApiInterface::class.java) ) {
暂停乐趣 getConnectionKt(): Response { 返回 apiInterface.ConnectionKt().awaitResponse() } }
最后,在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();
希望它有所帮助!