我是RxJava的新手所以请原谅我,如果这听起来太新手了:-).
截至目前,我有一个抽象的CallbackClass,它实现了Retofit Callback.在那里我捕获了Callback的"onResponse"和"onError"方法,并在最终转发到自定义实现的方法之前处理各种错误类型.我还使用此集中式类来进行请求/响应应用程序日志记录和其他内容.
例如:对于来自我的服务器的特定错误代码,我在响应正文中收到一个新的Auth令牌,刷新令牌,然后clone.enqueue调用.当然,我的服务器的响应还有其他一些全局行为.
当前解决方案(无Rx):
public abstract void onResponse(Call<T> call, Response<T> response, boolean isSuccess);
public abstract void onFailure(Call<T> call, Response<T> response, Throwable t, boolean isTimeout);
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (_isCanceled) return;
if (response != null && !response.isSuccessful()) {
if (response.code() == "SomeCode" && retryCount < RETRY_LIMIT) {
TokenResponseModel newToken = null;
try {
newToken = new Gson().fromJson(new String(response.errorBody().bytes(), "UTF-8"), TokenResponseModel.class);
} catch (Exception e) {
e.printStackTrace();
}
SomeClass.token = newToken.token;
retryCount++;
call.clone().enqueue(this);
return;
}
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用API进行改型和杰克逊反序列化。标题“没有创建者,就像默认构造一样,存在”中出现的错误:无法从对象值反序列化(没有基于委托人或基于属性的创建者)出现在onFailure中。
这是我要获取的JSON:
{
"data": {
"repsol_id": "1129",
"name": "ES-MASSAMÁ",
"latitude": "38.763733333",
"longitude": "-9.258619444000001",
"address": "RUA GENERAL HUMBERTO DELGADO, LT.16",
"post_code": "2745-280",
"location": "QUELUZ",
"service_store": 1,
"service_mechanical_workshop": 0,
"service_restaurant": 0,
"service_wash": 1
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的HomeFragment:
onCreate(){
viewModel.retrieveStation().observe(this, Observer {
dataBinding.favouriteStationTxt.text = it.name
})
}
Run Code Online (Sandbox Code Playgroud)
这是我的viewModel:
class HomeViewModel @Inject constructor(
private val stationRepository: StationRepository
) : ViewModel() {
private val station = MutableLiveData<Station>()
fun retrieveStation():LiveData<Station> = station
fun loadStations(stationId:Int){
stationRepository.getStationFromId(stationId,{ station.postValue(it)},{})
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的存储库:
class StationRepository @Inject constructor(var apiManager: ApiManager) {
fun …Run Code Online (Sandbox Code Playgroud) 我正在使用带有 Kotlin 协程的 Retrofit 2.7.1。
我有一个 Retrofit 服务定义如下:
@PUT("/users/{userId}.json")
suspend fun updateUserProfile(
@Path("userId") userId: String,
@Query("display_name") displayName: String) : Void
Run Code Online (Sandbox Code Playgroud)
此调用返回HTTP 204 No Content响应,这会导致 Retrofit 崩溃:
kotlin.KotlinNullPointerException: Response from com.philsoft.test.api.UserApiService.updateUserProfile was null but response body type was declared as non-null
at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:43)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:129)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Run Code Online (Sandbox Code Playgroud)
如何在改造中使用协程处理 204 响应而不会崩溃?
我试图使用Retrofit2.0.2获得原始响应.
到目前为止,我尝试使用以下代码行打印响应,但它打印的地址而不是确切的响应正文.
Log.i("RAW MESSAGE",response.body().toString());
compile 'com.squareup.retrofit2:retrofit:2.0.2'
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
GitApi gitApi = retrofit.create(GitApi.class);
Call<Addresses> call = gitApi.getFeed(user);
call.enqueue(new Callback<Addresses>() {
@Override
public void onResponse(Response<Addresses> response, Retrofit retrofit) {
try {
mDisplayDetails.setText(response.body().getSuburbs().get(0).getText());
**Log.i("RAW MESSAGE",response.body().toString());**
} catch (Exception e) {
mDisplayDetails.setText(e.getMessage());
}
mProgressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onFailure(Throwable t) {
mDisplayDetails.setText(t.getMessage());
mProgressBar.setVisibility(View.INVISIBLE);
}
});
Run Code Online (Sandbox Code Playgroud) 我已经开发了一个使用rxJava改造的Android应用程序,现在我正在尝试使用Mockito设置单元测试,但我不知道如何模拟api响应以创建不做真正的测试电话但有假响应.
例如,我想测试方法syncGenres对我的SplashPresenter工作正常.我的课程如下:
public class SplashPresenterImpl implements SplashPresenter {
private SplashView splashView;
public SplashPresenterImpl(SplashView splashView) {
this.splashView = splashView;
}
@Override
public void syncGenres() {
Api.syncGenres(new Subscriber<List<Genre>>() {
@Override
public void onError(Throwable e) {
if(splashView != null) {
splashView.onError();
}
}
@Override
public void onNext(List<Genre> genres) {
SharedPreferencesUtils.setGenres(genres);
if(splashView != null) {
splashView.navigateToHome();
}
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
Api类就像:
public class Api {
...
public static Subscription syncGenres(Subscriber<List<Genre>> apiSubscriber) {
final Observable<List<Genre>> call = ApiClient.getService().syncGenres();
return call
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(apiSubscriber);
} …Run Code Online (Sandbox Code Playgroud) 所以我有一个模特Model.
public class Model { .... }
Run Code Online (Sandbox Code Playgroud)
这有两个子类:
public class SubmodelA extend Model { .... }
Run Code Online (Sandbox Code Playgroud)
和
public class SubmodelB extend Model { .... }
Run Code Online (Sandbox Code Playgroud)
这三个都是在Data课堂上包装的.
public class ApiData<T extends Model> {
public T data;
}
Run Code Online (Sandbox Code Playgroud)
我的将军response wrapper看起来像这样:
public class ApiResponse<DATA> {
DATA data;
}
Run Code Online (Sandbox Code Playgroud)
"虚拟"api操作保持不变:
public interface Endpoints {
Call<ApiResponse<ApiData>> getData();
}
Run Code Online (Sandbox Code Playgroud)
我有一个retrofit2.Callback处理响应的实现:
public class ApiCallbackProxy<T> implements retrofit2.Callback<T> {
public interface ApiResultListener<RESPONSE_TYPE> {
void onResult(RESPONSE_TYPE response, ApiError error);
}
private ApiResultListener<T> …Run Code Online (Sandbox Code Playgroud) 我刚刚浏览了他们的主页,它说,
适用于Android和Java的类型安全的HTTP客户端
为什么Retrofit将自己宣传为Type Safe,而其他图书馆(许多其他受欢迎的图书馆)则没有?
在你回答之前......
有一个答案,同样的问题在这里.它说,
类型安全性是编程语言阻止或防止类型错误的程度.类型错误是由程序的常量,变量和方法(函数)的不同数据类型之间的差异引起的错误或不期望的程序行为,例如,将整数(int)视为浮点数(浮点数).这在静态类型语言(如Java和C)中很常见
因此,Retrofit可以防止此类错误
如果这确实是答案,那么许多库会阻止这些类型的错误,但它们都不会作为类型安全广告.那是营销吗?
我认为上述答案不充分,因为类型安全的定义尚未得到认真对待.
无论如何,还有另一篇文章定义了类型安全.他们给出了例子:
类型安全意味着编译器将在编译时验证类型,如果尝试将错误的类型分配给变量,则抛出错误.
一些简单的例子:
Run Code Online (Sandbox Code Playgroud)// Fails, Trying to put an integer in a string String one = 1; // Also fails. int foo = "bar";这也适用于方法参数,因为您将显式类型传递给它们:
Run Code Online (Sandbox Code Playgroud)int AddTwoNumbers(int a, int b) { return a + b; }如果我尝试使用以下方法调用:
Run Code Online (Sandbox Code Playgroud)int Sum = AddTwoNumbers(5, "5");
根据上面的定义,它将是语言(Java),而不是特定于TypeSafe的库.
所以,我再次问,为什么Retrofit将自己宣传为类型安全库?
使用Retrofit时,我知道您可以使用它@FieldMap Map<String, String> options来指定可选查询.
假设我有一个api调用,它有2个必填字段和3个可选字段.
我该如何格式化这些电话?
它会是什么样的
Call<Response> getStuff(@Query("user_id") String userId, @Query("password") String password, @FieldMap Map<String, String> options)
Run Code Online (Sandbox Code Playgroud)
或者整个事情是一个单独的@FieldMap:
Call<Response> getStuff(@FieldMap Map<String, String> options)
使用此选项,您只需填写必填字段然后null用于选项吗?
我试图PUT在我的Retrofit实例上调用一个方法:
Response<UpdateUserProfileResponse> response = App.getService().updateUserProfile(//A good 26 parameters).execute();
Run Code Online (Sandbox Code Playgroud)
其中的参数updateUserProfile()是String,Boolean和one的混合List<MyObject>.当我调用此方法时,我收到以下错误:
Throwing new exception 'length=238; index=1366' with unexpected pending exception: java.lang.ArrayIndexOutOfBoundsException: length=238; index=1366
06-28 21:53:12.458 3928-6610/com.subby.development A/art: art/runtime/thread.cc:1329] at retrofit2.Response
Run Code Online (Sandbox Code Playgroud)
更新
我发现了这个问题.有两个RealmList<BackgroundString>导致问题.当我评估两个RealmLists时,我得到:
Unable to evaluate the expression method threw 'java.lang.IllegalStateException' exception.
我正在执行网络请求,我发送文件和消息.我想有一个取消当前请求的选项.我发现了两个类似的问题,并且都建议observable.subscribe(Observer)返回具有方法的Subscription对象unsubscribe().
在我的情况下,我使用observable.subscribe(Observer)哪个是无效的.这是我的代码:
Observable<MessengerRaw> observable = mModel.sendMessage(message, companion, description, multiParts);
observable.subscribe(new Observer<MessengerRaw>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(MessengerRaw value) {
if (getView() != null) {
((MessengerActivity) getView()).resetMessegeView();
((MessengerActivity) getView()).updateMessageList();
}
}
@Override
public void onError(Throwable e) {
getData().remove(0);
if (getView() != null) {
((MessengerActivity) getView()).updateMessageList();
}
}
@Override
public void onComplete() {
hideProgress();
}
});
Run Code Online (Sandbox Code Playgroud)
那么如何取消订阅/取消我的请求?谢谢.