Używanie Retrofit w Androidzie a pobieranie konkretnego obiektu

0

Potrzebuję zalogować się na swój serwer.
Wysyłam zapytanie HTTP GET używając Retrofita (+gson +okhttp). Tak wygląda implementacja interfejsu:

public interface LoginLogoutService {
    @GET("/api/user")
    void idLogin(
            @Query("action") String action,
            @Query("id") String id,
            @Query("password") String password,
            Callback<ResponseLogin> cb
    );
}

Tak wygląda moja obsługa tego:

    private boolean powerLogin(){

        boolean status = false;

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(url)
                .build();

        final LoginLogoutService loginLogoutService = restAdapter.create(LoginLogoutService.class);

        loginLogoutService.idLogin("login", powerId, powerPassword, new Callback<ResponseLogin>() {

            @Override
            public void success(ResponseLogin responseLogin, retrofit.client.Response response2) {
                Log.i("INFO", "ResponseUsers: " + responseLogin.getStatus());

            }

            @Override
            public void failure(RetrofitError retrofitError) {
                Log.e("ERR", retrofitError.getUrl());
                Log.e("ERR", retrofitError.getResponse().getReason());
            }
        });


        return status;
    }

Pozytywna odpowiedź z serwera wygląda tak:

{
   "status": "OK"
}

Po mojej metodzie widzicie, że próbuję w jakiś sposób uzyskać odpowiedź czy logowanie się powiodło czy nie. Chciałbym dostać ten obiekt.

Próbowałem zaimplementować coś w ten sposób:

...    
static RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(url)
        .build();
...
static LoginLogoutService loginLogoutService = restAdapter.create(LoginLogoutService.class);
...
private boolean powerLogin2(){
        Response response = loginLogoutService.objectIdLogin("login", powerId, powerPassword);
        return response.getStatus() == 200;
    }

Razem z retrofitem:

    @GET("/api/user")
    Response objectIdLogin(
            @Query("action") String action,
            @Query("id") String id,
            @Query("password") String password
    );

... ale takie rozwiązanie jest synchroniczne i częstuje mnie Networking on main.

Wytłumaczcie proszę jak idiocie - jak powinienem rozwiązać ten problem?
Okej, pewnie jakoś przepuszczanie jednej wartości bym pominął. Ale mam jeszcze do przerobienia metodę getUser, która obiera mi jeden obiekt z kilkoma polami. W dokumentacji i przykładach w necie nie znalazłem rozwiązania odpowiadającego mojemu problemowi...

0

Nie używałem Retrofita, ale myślę że obsługę odpowiedzi (wyciągnięcie statusu) musisz zrobić w callbacku.

loginLogoutService.idLogin("login", powerId, powerPassword, new Callback<ResponseLogin>() {
 
            @Override
            public void success(ResponseLogin responseLogin, retrofit.client.Response response2) {
                Log.i("INFO", "ResponseUsers: " + responseLogin.getStatus());
              
                 // z response2 wyciągasz status http, to już się dzieje w main thread więc stąd można zaktualizować UI
            }
 
            @Override
            public void failure(RetrofitError retrofitError) {
                Log.e("ERR", retrofitError.getUrl());
                Log.e("ERR", retrofitError.getResponse().getReason());
            }
        });

Poza tym podejrzewam, że w Retroficie w momencie wystąpienia innej wartości statusu niż 200 automatycznie wywoływana jest metoda failure. Ale to trzeba zajrzeć do dokumentacji.

0

Tak, nie ma retry, jest tylko jedna próba. Ewentualnie można skorzystać z rozszerzenia rx java (ale wątpię aby autor tematu sobie poradził). Najlepiej będzie jak użyjesz robospice (ta biblioteka ma specjalny moduł do integracji z retrofit).

0

To może postawię pytanie trochę szerzej. Czy Retrofit jest w stanie obsłużyć mi takie zapytania w jakiś przyzwoity sposób:

action=getById&id=user_id
np. /api/user?action=getById&id=5629499534213120

czy
action=login&id=user_id&password=password
np. /api/user?action=login&id=5629499534213120&password=21232f297a57a5a743894a0e4a801fc3

...w taki sposób abym dostawał jakąś fizyczną rzecz do zabawy? Na przykład obiekt User aby potem go wkomponować w UI, czy coś w ten deseń? Bawię się tym problemem od pewnego czasu i z minuty na minutę czuję się coraz głupszy.

0

Masz przykład: https://github.com/octo-online/RoboSpice-samples/tree/release/robospice-sample-retrofit
Jest tam dokładnie to co chcesz osiągnąć.

0

To teraz zajmę się rozgryzaniem Robospice.
A w międzyczasie... To w takim razie do czego służy czysty Retrofit?

0

Przecież Retrofit w standardzie używa GSON'a do konwersji jsonowej odpowiedzi na obiekty javowe. A jak to nie pasuje to da rade napisać customowy converter. Chyba, że ja dalej nie rozumiem co tak naprawde chcesz osiągnąć :)

0

Jak już napisałem - z każdą minutą walki z tym problemem staję się coraz głupszy.
Odpowiadając na pytanie "co chcę osiągnąć"

Chciałbym Retrofitem pobrać jakiegoś JSONa i się nim pobawić.
Moja metoda w pierwszym poście... działa. Dostaję z niej obiekty w Callbacku (a dokładnie w obiekcie ResponseLogin, który w gruncie rzeczy jest POJO-reprezentacją tego JSONa) i dopóki jestem wewnątrz tej metody mogę robić co chcę. Na konsolę wyrzucam sobie co tylko dusza zapragnie i moje szczęście jest nieskończone.
Jednakże nie samą konsolą człowiek żyje i chciałbym mimo wszystko ten obiekt jakoś wydestylować. O tę jedną głupotę mi się "tylko" rozchodzi.

Myślę, że brakuje mi piątej klepki fundamentalnej wiedzy z programowania, ale po prostu nie wiem w jaki sposób mam wyciągnąć ten jeden zakichany obiekt.

0

Opakuj to wywołanie z callbackiem w klasie, gdzie przekazujesz listenera który się komunikuje z klasą obsługi UI (fragment, activity). Ewentualnie przekazuj callback bezpośrednio z UI, wtedy będziesz miał dostęp do kontrolek.

0

Okej, dostęp do kontrolek mogę mieć.
Tylko mój niecny plan jest taki:

  1. Pobierz dane z EditTextboxów
  2. Uruchom metodę onLoginClick()
  3. Zmontuj stosowne zapytanie.
  4. Otrzymaj odpowiedź:
    5a. Jeśli "false" - stosowny komunikat o błędzie.
    5b. Jeśli "true" - pobierz dane użytkownika z serwera, wyświetl nowe Activity z "Witaj <imię> <nazwisko>". (Ekran logowania z różnymi fragmentami to inne Activity niż ekran Navigation Drawer, gdzie dzieją się różne cuda).

Już teraz ta metoda znajduje się w MainActivity i teoretycznie powinienem mieć dostęp do kontrolek. To rozwiązanie jest jednak skrajnie nieelastyczne. W momencie kiedy skończę się bawić i wychodzę z metody Retrofitowej to "puszczam" dane i mi one przepadają.

1 użytkowników online, w tym zalogowanych: 0, gości: 1