2017-02-16 11 views
0

Я вызываю API на веб-сервер, и я возвращаю его обратно в метод onResponse.Возвращаемая переменная from onResponse Retrofit

Теперь я хочу сохранить этот идентификатор и вернуть этот идентификатор в возврате метода doLogin. Как я могу получить идентификатор переменной в операторе return?

Это мой код:

public class LoginController { 

    public static String doLogin(String loginMail, String loginPassword) { 

     //Logging Retrofit 
     final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); 

     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("###URLTOAPICALL###") 
       .client(client) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 

     APIService service = retrofit.create(APIService.class); 
     Call<JsonElement> call = service.doLogin(loginMail, loginPassword); 

     call.enqueue(new Callback<JsonElement>() { 
      @Override 
      public void onResponse(Call<JsonElement> call, Response<JsonElement> response) { 

       if (response != null) { 
        JSONObject obj = null; 

        try { 
         obj = new JSONObject(response.body().toString()); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 

        JSONObject setup = null; 
        try { 
         setup = obj.getJSONObject("setup"); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 

        if(setup != null) { 
         try { 
          Setup stp = new Setup(); 
          stp.setUserId(setup.getInt("id")); 

          //I WANT HERE TO SAVE MY ID 

         } catch (JSONException e) { 
          e.printStackTrace(); 
         } 


        } 
       } 
      } 

      @Override 
      public void onFailure(Call<JsonElement> call, Throwable t) { 
       Log.v("ERROR", t+""); 
      } 


     }); 

     return "I WANT RETURN THAT ID HERE"; 
    } 
} 
+0

объявить 'int id;' и затем установить id 'id = setup.getInt (" id ");'. Теперь 'return id' в конце –

+0

Короткий ответ: вы не можете .....' onResponse' - асинхронный обратный вызов –

+0

Этот комментарий не помогает вообще. onResponse isync, но ответ isnt (если вы вызываете execute вместо enqueue). –

ответ

2

Как дооснащения асинхронный не возвращаются из метода вместо использования интерфейса обратного вызова.

public class LoginController { 

    public interface LoginCallbacks{ 
     void onLogin(String id); 
     void onLoginFailed(Throwable error); 
    } 

    public static void doLogin(String loginMail, String loginPassword, final LoginCallbacks loginCallbacks) { 

     //Logging Retrofit 
     final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); 

     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("###URLTOAPICALL###") 
       .client(client) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 

     APIService service = retrofit.create(APIService.class); 
     Call<JsonElement> call = service.doLogin(loginMail, loginPassword); 

     call.enqueue(new Callback<JsonElement>() { 
      @Override 
      public void onResponse(Call<JsonElement> call, Response<JsonElement> response) { 

       if (response != null) { 
        JSONObject obj = null; 

        try { 
         obj = new JSONObject(response.body().toString()); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 

        JSONObject setup = null; 
        try { 
         setup = obj.getJSONObject("setup"); 
        } catch (JSONException e) { 
         e.printStackTrace(); 
        } 

        if(setup != null) { 
         try { 
          Setup stp = new Setup(); 
          stp.setUserId(setup.getInt("id")); 

          //I WANT HERE TO SAVE MY ID 
          if (loginCallbacks != null) 
           loginCallbacks.onLogin(setup.getInt("id")); 
         } catch (JSONException e) { 
          e.printStackTrace(); 
         } 


        } 
       } 
      } 

      @Override 
      public void onFailure(Call<JsonElement> call, Throwable t) { 
       Log.v("ERROR", t+""); 
       if (loginCallbacks != null) 
        loginCallbacks.onLoginFailed(t); 
      } 


     }); 
    } 
} 

метод вызова:

doLogin("email", "password", new LoginCallbacks() { 
      @Override 
      public void onLogin(String id) { 

      } 

      @Override 
      public void onLoginFailed(Throwable error) { 

      } 
     }); 
+0

Создание обратного вызова, чтобы избежать использования метода, который уже создан (execute()), никогда не является хорошей идеей. –

+0

привет @ EmanuelSeibold, ответ Pratik Popat был полезен для меня, могу ли я спросить, почему вы говорите, что это не хорошая практика для получения ответа? –

+0

Вы должны либо использовать свой логин в своей очереди, либо запустить в потоке main/ui, чтобы обновить свой ui или использовать поток и выполнить, который уже находится в потоке ui. Создание «onLogin» и «onLoginFailed» является избыточным, поскольку дооснащение имеет onResponse и onFailure. –

0

Вы не можете, так как вызов, который вы запрашиваете является асинхронной. Если вы хотите запустить его в том же потоке, вы должны избегать использования очереди и использовать execute(). Имейте в виду, что вам нужно создать поток, поскольку вы не можете использовать сетевые операции в одном и том же потоке.

Вы можете решить с помощью наблюдаемыми или использовать выполнить как в данном случае (не тестировался)

public static String doLogin(String loginMail, String loginPassword) { 

      //Logging Retrofit 
      final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
      interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
      OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); 

      Retrofit retrofit = new Retrofit.Builder() 
        .baseUrl("###URLTOAPICALL###") 
        .client(client) 
        .addConverterFactory(GsonConverterFactory.create()) 
        .build(); 

      APIService service = retrofit.create(APIService.class); 
      Call<JsonElement> call = service.doLogin(loginMail, loginPassword); 

      try { 
       Response response = call.execute(); 
       if (response.isSuccessful()) { 

        // do your stuff and 

        return yourString; 

       } 
      }catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
} 

Вы можете назвать это в вашей деятельности с помощью

new Thread(new Runnable() { 
     @Override 
     public void run() { 
      String var = doLogin("email", "paswsord"); 
     } 
    }); 

Позаботьтесь, что если вы хотите обновите свой пользовательский интерфейс, вы должны использовать

runOnUiThread(); 
+0

Я пробую ваше решение, но я не могу написать возврат на эту позицию ...? – AlfaLaurens

+0

Сир. return response.body(); и в конце возвращает null; или все, что вы хотите вернуть, в случае его отказа. –

1

Хотя функция call.execute() является синхронной, она тригг сбой приложений на Android 4.0 или новее, и вы получите NetworkOnMainThreadException. Вы должны выполнить асинхронный запрос, инициализирующий вашу глобальную переменную, в исполняемый поток. На ваше имя класса Runnable добавить implementation.Your getDataFunction() будет выглядеть примерно так:

public void getData(){ 
    Call<JsonElement> call = service.doLogin(loginMail, loginPassword); 

    call.enqueue(new Callback<JsonElement>() { 
     @Override 
     public void onResponse(Call<JsonElement> call, Response<JsonElement> response) { 

      if (response.isSuccessful() && response != null) { 
       jsonObject = response.body().toString();//initialize your global variable 
      } 
     } 

     @Override 
     public void onFailure(Call<JsonElement> call, Throwable t) { 
      Log.v("ERROR", t+""); 
     } 
    }); 

} 

@Override 
pulic void run(){ 
    getDataFunction(); 
    //here you can use your initialized variable 
} 

Теперь на вашем OnCreate функции создания нити запуска и запустить его.

Thread thread = new Thread(this); 
thread.start(); 

Это то, как он решил аналогичную проблему.

Смежные вопросы