标签: retrofit2

RxJava + Retrofit - >用于API调用的BaseObservable,用于集中响应处理

我是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)

android rx-java rx-android retrofit2

18
推荐指数
1
解决办法
2816
查看次数

没有创建者,如默认构造,不存在:无法从对象值反序列化(没有基于委托或基于属性的创建者

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

android jackson kotlin retrofit2

18
推荐指数
13
解决办法
4万
查看次数

如何使用 Kotlin 协程在 Retrofit 中处理 204 响应?

我正在使用带有 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 响应而不会崩溃?

android retrofit retrofit2 kotlin-coroutines

18
推荐指数
4
解决办法
7238
查看次数

如何使用Retrofit 2.0获得原始响应和请求

我试图使用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)

java android retrofit okhttp retrofit2

17
推荐指数
2
解决办法
1万
查看次数

单元测试android应用程序与改造和rxjava

我已经开发了一个使用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)

android mocking mockito rx-java retrofit2

17
推荐指数
1
解决办法
1万
查看次数

不兼容的类型推断类型不符合等式约束

所以我有一个模特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)

java generics retrofit retrofit2

17
推荐指数
1
解决办法
4459
查看次数

为什么Retrofit会宣传为"Type Safe"库?

我刚刚浏览了他们的主页,它说,

适用于Android和Java的类型安全的HTTP客户端

为什么Retrofit将自己宣传为Type Safe,而其他图书馆(许多其他受欢迎的图书馆)则没有?

在你回答之前......

有一个答案,同样的问题在这里.它说,

类型安全性是编程语言阻止或防止类型错误的程度.类型错误是由程序的常量,变量和方法(函数)的不同数据类型之间的差异引起的错误或不期望的程序行为,例如,将整数(int)视为浮点数(浮点数).这在静态类型语言(如Java和C)中很常见

因此,Retrofit可以防止此类错误

如果这确实是答案,那么许多库会阻止这些类型的错误,但它们都不会作为类型安全广告.那是营销吗?

我认为上述答案不充分,因为类型安全的定义尚未得到认真对待.

无论如何,还有另一篇文章定义了类型安全.他们给出了例子:

类型安全意味着编译器将在编译时验证类型,如果尝试将错误的类型分配给变量,则抛出错误.

一些简单的例子:

// 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");
Run Code Online (Sandbox Code Playgroud)

根据上面的定义,它将是语言(Java),而不是特定于TypeSafe的库.

所以,我再次问,为什么Retrofit将自己宣传为类型安全库?

java android type-safety retrofit retrofit2

17
推荐指数
3
解决办法
859
查看次数

改进可选和必填字段

使用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用于选项吗?

android retrofit retrofit2

16
推荐指数
2
解决办法
1万
查看次数

ArrayIndexOutOfBoundsException - 改进调用

我试图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.

android retrofit2

16
推荐指数
4
解决办法
4474
查看次数

改造2 + RxJava取消/取消订阅

我正在执行网络请求,我发送文件和消息.我想有一个取消当前请求的选项.我发现了两个类似的问题,并且都建议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)

那么如何取消订阅/取消我的请求?谢谢.

android retrofit2 rx-java2

16
推荐指数
2
解决办法
1万
查看次数