【问题标题】:How can I return value from onResponse of Retrofit v2如何从 Retrofit v2 的 onResponse 返回值
【发布时间】:2019-01-02 20:21:59
【问题描述】:

我想从我的函数中返回一个字符串值。但不知如何处理?我尝试了最终的单数组解决方案,但没有成功。

这是我的代码:

public String revealCourtPlace(String courtID)
{

    BaseService.getInstance().getUniqueCourt(Session.getToken(),courtID).enqueue(new Callback<JsonObject>()
    {
        @Override
        public void onResponse(Call<JsonObject> call, Response<JsonObject> response)
        {

            JsonObject object = response.body();
            boolean success = object.get("success").getAsBoolean(); //json objesinde dönen success alanı true ise
            if (success)
            {
                JsonArray resultArray = object.get("data").getAsJsonObject().get("result").getAsJsonArray();
                for (int i = 0; i < resultArray.size(); i++)
                {
                    JsonObject jsonInfoResult = resultArray.get(i).getAsJsonObject();
                    String courtName=jsonInfoResult.get("name").getAsString();
                }

            }

        }

        @Override
        public void onFailure(Call<JsonObject> call, Throwable t)
        {

        }

    });

    //return ?
}

【问题讨论】:

  • onResponse 被异步调用,即很有可能在您从revealCourtPlace 返回之后。
  • 你说,有没有办法获取字符串值?
  • 你需要构建你的逻辑以使其更具反应性,例如响应异步事件/更新。以RxJava为例(retrofit也支持RxJava
  • 你使用什么包包含JsonObject?为什么不org.json

标签: android retrofit retrofit2


【解决方案1】:

onResponse 是异步的,所以它很可能会在revealCourtPlace 返回后完成。

你不能像这样从onResponse 内部返回任何东西。但是,您可以向上传递值或重组代码以使用 Rx 之类的东西。

让我解释一下。因此,一种选择是通过回调传递您想要的字符串值。假设你有接口:

public interface RevealCourtPlaceCallbacks {
     void onSuccess(@NonNull String value);

     void onError(@NonNull Throwable throwable);
}

这些是任何想要接收网络调用价值的人都必须实现的方法。例如,您可以通过将其传递给方法 revealCourtPlace

来使用它
public void revealCourtPlace(String courtID, @Nullable RevealCourtPlaceCallbacks callbacks)
{  
   BaseService.getInstance()
      .getUniqueCourt(Session.getToken(),courtID)
      .enqueue(new Callback<JsonObject>() {
    @Override
    public void onResponse(Call<JsonObject> call, Response<JsonObject> response)
    {

        JsonObject object = response.body();
        boolean success = object.get("success").getAsBoolean(); //json objesinde dönen success alanı true ise
        if (success)
        {
            JsonArray resultArray = object.get("data").getAsJsonObject().get("result").getAsJsonArray();
            for (int i = 0; i < resultArray.size(); i++)
            {
                JsonObject jsonInfoResult = resultArray.get(i).getAsJsonObject();
                String courtName=jsonInfoResult.get("name").getAsString();

                if (callbacks != null)
                  calbacks.onSuccess(courtName);
            }

        }

    }

    @Override
    public void onFailure(Call<JsonObject> call, Throwable t)
    {
        if (callbacks != null)
            callbacks.onError(t);
    }

  });
}

需要注意的重要事项:该方法返回 void。您将回调作为参数传递。这些回调必须由调用方法的人实现,或者作为在调用点实现的匿名类。

这使您能够异步接收字符串courtName,而不必担心返回值。

还有另一个选项可以让您的代码具有响应性。这是更多的工作和范式的转变。它还需要 Rx java 方面的知识。我将在这里留下一个如何做到这一点的例子。请记住,有几种方法可以做到这一点。

首先,您应该以不同的方式定义改造接口。返回类型现在必须是可观察的:

public interface CourtApiClient {
    @GET(/*...*/)
    Single<JsonObject> getUniqueCourt(/*...*/);
}

我不是很清楚你调用的整个接口细节,但是这里重要的部分是返回类型现在是Single。这是一个只发出一个项目或错误的 Rx 可观察对象。类型也应该是 JsonObject 以外的其他类型,但这很难从您的代码中看出它应该是什么。无论如何,这也可以。

下一步是简单地从您的 revealCourtPlace 方法返回结果:

public Single<JsonObject> revealCourtPlace(String courtID, @Nullable RevealCourtPlaceCallbacks callbacks)
{  
   return BaseService.getInstance()
      .getUniqueCourt(Session.getToken(),courtID);
}

这里的关键区别在于该方法现在返回可观察对象,您可以随时订阅它。这使得流程看起来是同步的,尽管它实际上是异步的。

您现在可以选择将JsonObject 映射到您想要的几个字符串,或者在您的订阅者中进行解析。

编辑

由于您在 cmets 中询问如何调用您的函数,因此有可能:

revealCourtPlace("some court id", new RevealCourtPlaceCallbacks() {
       @Override
       public void onSuccess(@NonNull String value) {
          // here you use the string value
       }

       @Override
       public void onError(@NonNull Throwable throwable) {
          // here you access the throwable and check what to do
       }
  });

或者,您可以让调用类实现这些回调并简单地传递this

revealCourtPlace("some court id", this);

【讨论】:

  • 感谢您指导回复先生。真是太神奇了。但是怎么能调用我的函数呢? revealCourtName(courtID,?);
  • @YunusHaznedar 我已经编辑了我的答案。看看它是否对你有帮助!
  • 感谢您的指导答复先生。它将帮助我了解我做错了什么。再次感谢。
【解决方案2】:

使用 retrofit2 可以进行同步调用:

Callback<JsonObject> callback = BaseService.getInstance().getUniqueCourt(Session.getToken(),courtID)
Response<JsonObject> response = callback.execute();
...

但是,同步请求会在 Android 4.0 或更高版本上触发应用崩溃。你会遇到NetworkOnMainThreadException 错误。

更多信息here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 2020-07-12
    • 1970-01-01
    • 2017-11-18
    相关资源
    最近更新 更多