Проблема с модифицированными обратными вызовами

#java #rest #retrofit

#java #rest #модернизация

Вопрос:

У меня есть модифицированный интерфейс, который определяет метод с обратным вызовом, подобный этому :

 public interface ApiManagerService {
    @GET("/users/")
    void getUsers(Callback<List<GitHubMember>>);
}
  

GitHubMember это просто POJO с 3 полями: id, login и URL. Я создал класс под названием ResponseHandler, куда я могу перенести ответ из обратного вызова. Вот как это определить :

 public class ResponseHandler<T> {

private T response;

private RESPONSE_CODE responseCode;

private String detail;

public static enum RESPONSE_CODE {
    OK,     // if request suceed
    APP_ERROR, //technical error for instance network
    TECHNICAL_ERROR // app technical error
}

//getters and setters
  

Вот как я использую этот класс с методом getUsers :

 public ResponseHandler<List<GitHubMember>> getUsers() {
    ResponseHandler<List<GitHubMember>> handler = new ResponseHandler<List<GitHubMember>>();
    apiManagerService.getUsers(new Callback<List<GitHubMember>> cb) {
        @Override
        public void success(List<GitHubMember> users, Response response) {
            responseHandler.setResponse(users);
            responseHandler.setResponseCode(ResponseHandler.RESPONSE_CODE.OK);
        }

        @Override
        public void failure(RetrofitError error) {
            try {  
            handler.setResponseCode(ResponseHandler.RESPONSE_CODE.APP_ERROR);
            responseHandler.setDetail(error.toString());
            }catch (Exception e){
                handler.setResponseCode(ResponseHandler.RESPONSE_CODE.TECHNICAL_ERROR);
                responseHandler.setDetail(e.getMessage());
            }
        }
   }
   return handler;
  

}

Проблема, с которой я сталкиваюсь, заключается в том, что после выполнения этого метода и ввода обратного вызова все поля в ResponseHandler равны нулю. Я полностью уверен, что обратные вызовы выполняются, потому что я установил точки останова в обратном вызове во время отладки.

Объект apiManagerService правильно инициализирован с помощью класса RestAdapter.

Как я могу решить эту проблему?

Ответ №1:

apiManagerService.getUsers() только инициирует сетевой запрос и возвращает. Обратный вызов вызывается после того, как сеть ответила в фоновом потоке. Таким образом, к моменту return handler выполнения handler все еще пусто. Более того, даже если после обратного вызова будет выполнен какой-либо оператор возврата, вы можете не увидеть изменений, внесенных в общие переменные (поля обработчика) фоновым потоком из-за ограничений модели памяти Java.

Комментарии:

1. Есть идеи, как решить эту проблему? Я мог бы использовать countdownlatch для ожидания обратного вызова?

2. @Dimitri для этого вы можете использовать шину событий: опубликовать результат обратного вызова и обработать его в методе подписчика в Activity или другом компоненте. В качестве примера вы можете использовать Otto или EventBus.