Сеть в Android/Java — как мне выполнить обратный вызов класса API после обратного вызова с сервера?

Итак, я пишу приложение для Android на Java на основе приложения для iOS, над которым я также работаю, но этот вопрос больше касается того, как общаться с механизмом обратного вызова (например, с блоками в Objective-C 2.0) в Java.

Это приложение включает в себя работу в сети, аутентификацию и связь с сервером через API.

Я использую эту структуру: https://github.com/loopj/android-async-http

Я пытаюсь инкапсулировать всю сетевую модель в классы, чтобы сделать все чистым и простым (это кажется таким простым в iOS с делегатами и блоками, но java, похоже, не имеет НИ ОДНОГО из этих удобств). Итак, я использую это как руководство для обратных вызовов: http://www.gdgankara.org/2013/03/25/android-asynchronous-http-client-a-callback-based-http-client-library-for-android-and-android-smart-image-view/

Теперь предположим, что я хочу сделать вызов не из класса Activity, а из класса API, который можно вызвать из класса Activity, как я могу это сделать? Я легко знаю, как это сделать с блоками и делегатами в iOS, но как я могу сделать это с интерфейсами?


Например:

В iOS (используя общую сетевую структуру под названием AFNetworking) у меня есть 4 класса:

HTTPClient.ч/м

+(id)sharedHTTPClient
  {
    static dispatch_once_t pred = 0;
    __strong static id __httpClient = nil;
    dispatch_once(&pred, ^{
        NSString *baseURL = http://baseurl.com;
        __httpClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];
        [__httpClient setParameterEncoding:AFJSONParameterEncoding];        

    });
    return __httpClient;
}

APILogin.h/m

-(void)loginWithSuccessBlock:(void (^)(NSArray *responseArray))loginSuccess {
    HTTPClient *httpClient = [HTTPClient sharedHTTPClient];
    NSURLRequest *request = [httpClient requestWithMethod:@"GET" path:@"/api/login" parameters:nil];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        NSArray *response = [self.jsonParser parseResponseFromJSON:JSON];
        if (loginSuccess) {
            loginSuccess(response);
        }

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {  
        [APIErrorHandler handleError:error withHTTPResponse:response];
    }];

    [operation start];
}

ЛогинОбъект.ч/м

-(id)init
 {
     self = [super init];
     if(self) {
         [self.apiLogin loginWithSuccessBlock:^ void (NSArray *loginArray) {
                //process the array
          }];
     }
 }

ЛогинVC.ч/м

...
LoginObject *loginObj = [[LoginObject alloc] init];
...

Итак, что у меня есть до сих пор, используя библиотеку Android-Async-Http:

HTTPClient.java

public class HTTPClient extends AsyncHttpClient {
    public static HTTPClient sharedHTTPClient;
    public static String baseUrl = "http://baseurl.com";
    public HTTPClient {
        super();
    }
    ...
}

APILogin.java

public class APILogin {
    public void loginWithSuccessBlock() {
        HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
    httpClient.get("/api/login", new JsonHttpResponseHandler() {
         @Override
         public void onSuccess(JSONArray response) {
             // Successfully got a response
            ArrayList<LoginObject> loginInfo = this.jsonParser.parseLoginFromJSON(response);
            **NEED TO DO A CALL BACK!! Like with the blocks in iOS**
         }
        @Override
         public void onSuccess(JSONObject response) {
             // Successfully got a response
            // shouldn't be an object
            throw new IllegalArgumentException();
         }


         @Override
         public void onFailure(Throwable e, String response) {
             // Response failed :(
         }
    });
}

LoginObject.java

public class LoginObject {
    public LoginObject {
        this.apiLogin.loginWithSuccessBlock(**something something for a callback**);
    }
}

Надеюсь, я сделал это немного яснее, чего я пытаюсь достичь. Я хочу иметь возможность выполнить какой-то блок обратного вызова для объекта, вызвавшего вызов API, в случае успеха. Однако это не всегда будет один и тот же объект. LoginObject может иметь экземпляр APILogin.java, а также другой объект, поэтому я не могу использовать вторую ссылку выше, в которой вы можете указать конкретный класс, передать его и вызвать для него метод, потому что классы будут различных типов, а в Java нет универсального объекта-указателя (id или void*).


person Robby Cohen    schedule 20.06.2013    source источник
comment
Не могли бы вы конкретизировать свой вопрос, приведя пример? Я не понимаю, что вы подразумеваете под «обратным вызовом API после обратного вызова с сервера»? Это асинхронный материал, нет такого понятия, как "после"...   -  person verybadalloc    schedule 20.06.2013
comment
извините за неточность, но я обновил ответ подробным примером. спасибо!   -  person Robby Cohen    schedule 20.06.2013


Ответы (1)


Итак, я нашел свой собственный ответ, перепробовав множество вещей и просмотрев Интернет в поисках возможного решения. Что я придумал, так это в основном связать обработчики ответов.

Таким образом, для:

public class APILogin {
    public void loginWithSuccessBlock(**final JsonHttpResponseHandler handler**) {
        HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
        httpClient.get("/api/login", handler);
    }
}

public class LoginObject {
    public LoginObject {
        this.apiLogin.loginWithSuccessBlock(new JsonHttpResponseHandler(){
        ...
        );
    }
}

что не очень надежно, потому что не позволяет мне много настраивать, но сойдет.

person Robby Cohen    schedule 20.06.2013