【问题标题】:PATCH Verb in Android (OkHttp, Volley, Retrofit...)Android 中的 PATCH 动词(OkHttp、Volley、Retrofit...)
【发布时间】:2015-03-25 13:27:22
【问题描述】:

我知道类似的问题已经被问过好几次了,但我似乎找不到一个简单问题的解决方案:PATCH动词。

所以我问任何通过使用 OkHttp、Volley 或 Retrofit 解决了 Android 中 PATCH 问题的人(或者如果您使用了不同的方法或库,请分享)。

我花了 3 天时间四处挖掘,但找不到任何解决此问题的方法。我要做的就是通过在 .NET 环境中构建和运行的 RESTful API 对表进行部分更新。

我目前正在使用 Volley,但每次运行该应用程序时,我都会收到异常错误,说明类似于 PATCH is not an allowed...? 的内容,然后它给出了一系列可以使用的其他动词,例如“POST,放,拿……”。所以,一点帮助都没有。

我尝试过像这样使用OkHttp

  JSONObject infoRequestBody = new JSONObject();


    try {


        infoRequestBody.put("Salutation", "MRrr.");
        infoRequestBody.put("FirstName", "Work Now!!");
        infoRequestBody.put("LastName", "Test from my mobile again!! Okhttp");
        infoRequestBody.put("MiddleName", "From the Mobile");
        infoRequestBody.put("NickName", null);
        infoRequestBody.put("BirthDate", "1978-11-23T00:00:00.000Z");
        infoRequestBody.put("CompanyName", null);
        // infoRequestBody.put("RegDate", "2015-01-18T23:39:13.873Z");
        infoRequestBody.put("Gender", "Male");
        infoRequestBody.put("IsPregnant", null);
        infoRequestBody.put("IsNursing", null);
        infoRequestBody.put("WorkPhone", null);
        infoRequestBody.put("WorkPhoneExt", null);
        infoRequestBody.put("PhoneNumber", null);
        infoRequestBody.put("Address", "My android app working!!");
        infoRequestBody.put("Address2", null);
        infoRequestBody.put("City", null);
        infoRequestBody.put("State", "CA");
        infoRequestBody.put("ZipCode", null);
        infoRequestBody.put("EmailAddress", "email@me.com");
        infoRequestBody.put("Occupation", null);
        infoRequestBody.put("CountryofResidence", "United States");
        infoRequestBody.put("CountryCode", "US");
        infoRequestBody.put("Ethnicity", "Asian");
        infoRequestBody.put("ModifiedDate", "2015-01-18T23:39:13.873Z");
        infoRequestBody.put("ModifiedBy", null);
        infoRequestBody.put("AcceptedTerms", true);
        infoRequestBody.put("AcceptedPrivacyPolicyCheckbox", false);
        infoRequestBody.put("AcceptedUnder18ConsentCheckbox", false);
    } catch (JSONException e1) {
        e1.printStackTrace();
    }
  RequestBody body = com.squareup.okhttp.RequestBody.create(JSON, infoRequestBody.toString());


    com.squareup.okhttp.Request.Builder request = new com.squareup.okhttp.Request.Builder()
             .url("APIUrls.PATIENT_INFO_URL")
            .addHeader("Content-Type", "application/json")
            .addHeader("Accept", "application/json")
            .addHeader("X-ZUMO-APPLICATION", APIUrls.ZUMO_KEY)
            .patch(body);



    client.newCall(request).enqueue(new Callback() {




        @Override
        public void onFailure(com.squareup.okhttp.Request request, IOException e) {


        }

        @Override
        public void onResponse(com.squareup.okhttp.Response response) throws IOException {

            if (!response.isSuccessful()) throw new IOException("Unexpected code" + response);

            Headers responseHeaders = response.headers();
            for (int i = 0; i < responseHeaders.size(); i++) {
                System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
            }


            System.out.println(response.body().string());

        }
    });

但是client.newCall(request).enque(new Callback()... 给了我一个错误,说request 不能应用于Request.Builder

顺便说一下,我是 OkHttp 的新手。

无论如何,我一直在努力让PATCH 工作太久。也许我是在黑暗中拍摄,但如果有人对如何让“PATCH”工作有任何建议和想法,我将永远感激你。

感谢您的帮助。

【问题讨论】:

  • 您在.patch() 之后错过了对.build() 的呼叫。你想要Request,而不是Request.Builder
  • 您是否尝试过使用像 Rested 这样的 REST 客户端(众多 chrome 扩展程序之一等)来确保您的服务器支持请求?
  • @JacobTabak,是的,我有。一切正常,除非我尝试在 Android 中做同样的事情。

标签: android android-volley okhttp


【解决方案1】:

我还没有尝试过,但显然,如果您将 Retrofit 与 OkHTTP 的 OKClient 一起使用,那么 Retrofit 支持 @Patch 注释。

http://square.github.io/retrofit/javadoc/retrofit/http/PATCH.htmlRetrofit & HTTP Patch

【讨论】:

  • 截至 2016 年 3 月,我正在使用 Retrofit 2.0.0-beta4 成功地使用 PATCH,而没有包含任何进一步的库,如此处的答案中所述。
【解决方案2】:

正如 GreyBeardedGeek 所说,您可以使用 Retrofit + OkHttp 来实现这一点。

RestAdapter restAdapter = new RestAdapter.Builder()
                .setClient(new OkClient())
                .setEndpoint(ENDPOINT)
                .build();
MyPatchService patchService = restAdapter.create(MyPatchService.class);
UserUpdate updatedUser = new UserUpdate();
updatedUser.Salutation = "Mr";
updatedUser.FirstName = "Adam";
patchService.update(updatedUser);

MyPatchService 看起来像这样:

public interface MyPatchService {
    @PATCH("/some/update/endpoint")
    User update(UserUpdate updatedObject);
}

您的 UserUpdate 类可能如下所示:

public class UserUpdate {
    public String Salutation;
    public String FirstName;
    public String LastName;
}

如果您这样做,将发送的 JSON 将如下所示(请注意,LastName 未序列化,因为它从未设置 - 这可通过向 Retrofit 提供自定义 Gson 实例来配置):

{
  "Salutation": "Mr",
  "FirstName": "Adam"
}

请求/响应对象是您通过网络发送/接收的对象的纯 Java 表示。作为补丁请求,您可以让您的成员变量为 IntegerBoolean 等,如果未设置它们将不会被序列化(即,如果它们是 null)。

【讨论】:

  • 感谢@Adam 和@GreyBeardedGeek 的回复。那么,我作为 PATCH 发送的 JSON 对象会被添加到 restAdapter 对象中吗?像这样.setPatch(myJsonData),还是会在接口内部传递?抱歉问题:我是 OkHTTP 和 Retrofit 的新手。谢谢
  • 您只需创建请求/响应对象,然后编写接口以期望它们 - Retrofit 会为您完成所有序列化和反序列化。我将进一步更新示例,但我推荐having a good read about the magic that is Retrofit
  • 感谢您的帮助。我现在正在实施你在这里展示的一切。一件事:当你说User update(UserUpdate updatedObject);时,你的意思是说Userupdate(UserUpdate updatedObject);(UserUpdated(UserUpdated updatedObject);正确吗?
  • 不,它是按预期编写的 - 在此示例中,服务器返回完整更新的对象(在本例中为 User 对象)。我不知道对于接受带有 PATCH 动词的请求的端点来说,这是否是正确的行为。
  • 谢谢@Adam。会做。再次感谢,如果/当我让这个东西工作时,一定会报告:)
【解决方案3】:

好的!感谢@Adam 和所有帮助我走向正确方向的人。真的很感激。所以,这就是我最终做的事情(我几乎没有定制@Adam 发布的内容,这当然是正确的答案!):

首先,

我将UserUpdate 类设置如下:

public class UserUpdate {
public String Salutation;
public String FirstName;
public String LastName;
public String MiddleName;
public String NickName;

     //Setters and Getters...
  public String getSalutation() {
      return Salutation;
  }

  public void setSalutation(String salutation) {
      Salutation = salutation;
  }

  public String getFirstName() {
     return FirstName;
  }

  public void setFirstName(String firstName) {
     FirstName = firstName;
  }

  public String getLastName() {
      return LastName;
  }

  public void setLastName(String lastName) {
      LastName = lastName;
  }

public String getMiddleName() {
    return MiddleName;
}

public void setMiddleName(String middleName) {
    MiddleName = middleName;
}

public String getNickName() {
    return NickName;
}

 public void setNickName(String nickName) {
     NickName = nickName;
 }


}

然后我设置了interface class,称为PatientInfoAPI

public interface PatientInfoAPI{

@PATCH("/tables/PatientInformation/{id}")
  public void update(@Body UserUpdate updatedDAta, @Path("id") String  id,Callback<UserUpdate> response);


 }

请注意,我将表 id 传递为“PATCH'd”,最重要的是我有 @Body 注释,它允许我将数据传递给更新而不会出现错误(我试过没有它并且是出现错误)

最后在我的主要活动中:

 RestAdapter restAdapter = new RestAdapter.Builder()
            .setClient(new OkClient()) //very important!!!
            .setEndpoint(ENDPOINT)//base url
            .setRequestInterceptor(new RequestInterceptor() {//You may not need to pass headers, but I do, so this is how it's done.
                @Override
                public void intercept(RequestFacade request) {

                    request.addHeader("Content-Type", "application/json");
                    request.addHeader("Accept", "application/json");
                    request.addHeader("X-ZUMO-APPLICATION", APIUrls.ZUMO_KEY);

                }
            })
            .build();
    PatientInfoAPI patchService = restAdapter.create(PatientInfoAPI.class);

    UserUpdate updatedUser = new UserUpdate();
    updatedUser.setSalutation("Sr.");
    updatedUser.setFirstName("YesSirtItsWorking");
    updatedUser.setLastName("Bays");
    updatedUser.setMiddleName("ComeOn Now man!");
    updatedUser.setNickName("");

     //Passing the tableId along with the data to update
     patchService.update(updatedUser, APIUrls.TABLE_ID, new retrofit.Callback<UserUpdate>() {
        @Override
        public void success(UserUpdate userUpdates, retrofit.client.Response response) {


            Log.v("All is good", "Nickname:" +  userUpdates.getNickName().toString() + " Email: " + userUpdates.getEmailAddress().toString());



        }

        @Override
        public void failure(RetrofitError error) {

            Log.v("All is good", error.getLocalizedMessage().toString());


        }
    });

我知道有些步骤可能不是很复杂,但对于那些开始使用 Retrofit 和 OkHttp,最重要的是一直在努力让PATCH 与 Android 一起工作的人来说,这就是解决方案。同样,@Adam 的道具几乎可以指导我完成整个过程。 @Adam 是真正回答了这个问题的人——我只是把它们放在一起,供那些可能需要查看全貌的人使用。谢谢,@亚当!你是摇滚明星!

【讨论】:

    猜你喜欢
    • 2017-06-25
    • 2015-07-16
    • 2016-04-24
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多