Retrofit 2.0 как удалить?

Я использую модификацию 2.0 и реализую функцию удаления в своем приложении для Android, однако я не могу сделать это успешно, может ли кто-нибудь дать мне предложение?

Я пробовал оба:

@DELETE("books/{id}") void deleteBook(@Path("id") int itemId);

@DELETE("books/{id}") void deleteBook(@Path("id") int bookId, Callback<Response> callback);

Я получаю сообщение об ошибке java.lang.IllegalArgumentException: методы службы не могут возвращать значение void. для метода LibraryService.deleteBook.

Я также попробовал это:

Response deleteBook(@Path("id") int bookId);

Call<Response> deleteBook(@Path("id") int bookId);

независимо от того, использую ли я okhttp3.Response или retrofit2.Response, я получу ошибку: '*.Response' не является допустимым типом тела ответа. Вы имели в виду ResponseBody?

Может ли кто-нибудь дать мне успешный пример удаления? Я googled онлайн, но не могу найти достаточно информации. Большое спасибо.


person xiaoyaoworm    schedule 27.03.2016    source источник
comment
Какой импорт вы используете для аннотации DELETE? Смущен, почему запрос анализирует его как GET....   -  person Lucas Crawford    schedule 28.03.2016
comment
@Lucas Теперь очень запутался, import retrofit2.http.DELETE; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; Потому что, когда я реализую функцию PUT, но с тем же URL-адресом, @PUT("books/{id}") Call<Book> updateBook(@Path("id") int bookId , @Body Book book); я получаю ту же проблему, метод запроса ответа - GET   -  person xiaoyaoworm    schedule 28.03.2016
comment
Для следующего вопроса я создаю новый вопрос: stackoverflow.com/questions/36255825/   -  person xiaoyaoworm    schedule 28.03.2016


Ответы (1)


Сделайте это так, как вы отметили в прошлом:

Call<ResponseBody> deleteBook(@Path("id") int bookId);

Убедитесь, что вы вызываете поток пользовательского интерфейса через AsyncTask или какой-либо другой механизм потоковой передачи. Не уверен, что вы использовали RxJava + Retrofit 2 раньше, но это приятно.

Объект ResponseBody вернет результаты вызова. Это то, что я использую для некоторых запросов REST API, которые не возвращают объект сущности, и все, что мне нужно, это посмотреть код ответа.

Call<ResponseBody> deleteRequest = mService.deleteBook(123);
deleteRequest.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        // use response.code, response.headers, etc.
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        // handle failure
    }
});

Или, Джейк Уортон предлагает

Используйте Void, который не только имеет лучшую семантику, но и (немного) более эффективен в пустом случае и значительно более эффективен в непустом случае (когда вам просто наплевать на тело).

Так что у тебя есть:

Call<Void> deleteBook(@Path("id") int bookId);

Использование:

deleteRequest.enqueue(new Callback<Void>() {
    @Override
    public void onResponse(Call<Void> call, Response<Void> response) {
        // use response.code, response.headers, etc.
    }

    @Override
    public void onFailure(Call<Void> call, Throwable t) {
        // handle failure
    }
});

Это лучше, если все, что вам нужно, это код ответа, а не тело ответа.

РЕДАКТИРОВАТЬ 2: Упущено правильное определение обратного вызова. Исправлена ​​:)

person Lucas Crawford    schedule 27.03.2016
comment
Спасибо @Лукас. Это работает!!!!! Прежде чем увидеть ваш ответ, я думаю, что попробовал ResponseBody, но потерпел неудачу. Не уверен, какую часть я сделал неправильно. Да, вы правы, я думаю, что я должен поместить его в AsyncTask, иначе, если будет получено слишком много данных, он заблокирует мой пользовательский интерфейс. RxJava, не уверен, что это такое, но я проверю. Большое спасибо!!! - person xiaoyaoworm; 27.03.2016
comment
Он использует реактивное программирование для обработки сетевых запросов, таких как вы, + некоторые парадигмы функционального программирования, которые делают код чище. RxJava значительно упрощает работу с сетью в Java для сложных задач, я все еще изучаю ее сам, но многие компании начинают ее использовать и делают swtich - person Lucas Crawford; 27.03.2016
comment
У программы нет проблем с вашим предложением, но у меня есть другая проблема. Поскольку я выполняю работу по удалению, при вызове таким образом я получу response.code() = 200, и книга не будет удалена. Я попробовал Advanced Rest Cilent, при успешном удалении код ответа, показанный на расширении, — 204. У вас есть какие-то идеи по этому поводу? RxJava звучит интересно, я должен взглянуть, чтобы изучить ее. Спасибо за ваше предложение. - person xiaoyaoworm; 27.03.2016
comment
Да, @Lucas полностью согласен с вами, Void имеет смысл, потому что меня не волнует ничего, кроме кода ответа. - person xiaoyaoworm; 27.03.2016
comment
w3.org/Protocols/rfc2616/rfc2616-sec10.html Ответ код 204 означает, что сообщение было выполнено успешно, но объект не включен в тело сообщения (еще одна причина для использования Callback‹Void›). В предоставленной мной ссылке говорится: сервер выполнил запрос, но ему не нужно возвращать тело объекта, и он может захотеть вернуть обновленную метаинформацию. Ответ МОЖЕТ включать новую или обновленную метаинформацию в виде заголовков сущностей, которые, если они присутствуют, ДОЛЖНЫ быть связаны с запрошенным вариантом. Поэтому, когда вы видите код ответа 204, это означает, что вы успешно удалили. - person Lucas Crawford; 27.03.2016
comment
да, ты прав. С предоставленным вами кодом я могу получить только 200, а не 204, после того, как я получу 200, я перечислю все книги, обнаружив, что та, которую я удалил, все еще там. Моя проблема в том, почему я не могу получить 204 (это должно быть успешно удалено). Вот код, который я следую тому, что вы предложили: ` @DELETE(books/{id}) Call‹Void› deleteBook(@Path(id) int bookId);` deleteBookCall.enqueue(new Callback<Void>() { @Override public void onResponse(Call<Void> call, Response<Void> response) { if (response.isSuccessful()) {} - person xiaoyaoworm; 27.03.2016
comment
Интересный. Какой список вы проверяете, локализованный (где удаление не удалило бы его) или повторно извлекается из вашей базы данных? - person Lucas Crawford; 27.03.2016
comment
Вот что я сделал, он получит все книги на сервере, @GET(books) Call‹ArrayList‹Book›› listBooks(); Я также играю в расширение Advanced Rest Client Chrome. Оттуда я могу успешно удалить и получить 204. - person xiaoyaoworm; 27.03.2016
comment
Давайте продолжим обсуждение в чате. - person xiaoyaoworm; 27.03.2016
comment
Я нахожу, где я делаю ошибки. stackoverflow.com/a/36379787/2011900 Я очень ценю вашу помощь!!!! Спасибо!!! - person xiaoyaoworm; 03.04.2016