2016-06-16 4 views
-2

Я делаю простой экран входа в конструкцию материалов, в котором отображается диалоговое окно прогресса, в то время как модификация приобретает данные.Проблемы с обратным вызовом Retrofit 2 с потоком пользовательского интерфейса

Я недавно обновился до модификации 2, поэтому я совершенно новичок в этом.

Мой код LoginActivity:

private void login(){ 
     Log.d(TAG, "Attempting login"); 

     if(!validate()){ 
      onLoginFailure(); 
      return; 
     } 

     login_button.setEnabled(false); 

     progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog); 
     progressDialog.setIndeterminate(true); 
     progressDialog.setMessage("Authenticating..."); 
     progressDialog.show(); 

     String username = _usernameText.getText().toString().toLowerCase(); //all usernames are lowercase only 
     String password = _passwordText.getText().toString(); 

     //here we handle the NWL section. 

     startTime = System.currentTimeMillis(); 
     NWL.login(username, password, this); //This runs async to UI anyway. 
    } 

и другие функции в LoginActivity:

@BindView(R.id.login_button) 
Button login_button; 

public void loginOK() { 
     progressDialog.dismiss(); 
     login_button.setEnabled(true); 
     toastCreator.showToastLong("Login OK"); 
     Log.d(TAG, "Total time: " + (System.currentTimeMillis()-startTime)); 
} 

Мой код из моего NetworkLogic (НПУ) класс:

public void login(String username, String password, final LoginActivity loginActivity){ 
    LoginUser loginUser = new LoginUser(username, password); 

    Call<Username> call = apiService.login(loginUser); 
    Log.d(TAG, call.toString()); 
    call.enqueue(new Callback<Username>() { 
     @Override 
     public void onResponse(Call<Username> call, Response<Username> response) { 
      Log.d(TAG, "Responsecode : " + response.code()); 
      try { 
       Thread.sleep(2000); //To test if the progressdialog actually shows up 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      if(response.code()==200){ 
       loginActivity.loginOK(); 
      } else { 
       loginActivity.loginFail(); 
      } 
     } 

     @Override 
     public void onFailure(Call<Username> call, Throwable t) { 
      Log.d(TAG, "Failed: " + t.getMessage()); 
      loginActivity.loginFail(); 
     } 
    }); 
} 

Теперь я держу получение таких ошибок, как: - android.util.AndroidRuntimeException: Animators может работать только на нити петлителя (о loginbutton) - java.lang.RuntimeException: Невозможно создать обработчик внутри потока, который не называется Looper.prepare() (о toastCreator)

Я понимаю, что вызывает проблема (асинхронный поток из retrofit 2 выполняет вызовы), когда он должен передавать вызов в поток ui. Мой вопрос здесь, что является лучшим решением для решения этой проблемы? Конечно, я могу взломать код вместе с CountdownLatch и запустить весь асинхронный вызов как вынужденную синхронизацию, но на самом деле это не то, что я ищу. Должен ли я использовать обработчик? Если да, то какой был бы лучший способ реализовать это?

Весь код доступен: https://github.com/mathieudevos/pinkiponki-app

С нетерпением жду ответов!

ответ

3

Хорошо, так как никто не ответил на вопрос правильно, вот он!

Использование обработчика и отправка сообщений на него, похоже, делают трюк.

В OnCreate метод:

handler = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg){ 
      switch (msg.what){ 
       case 200: 
        //Got the good response 
        loginOK(); 
        break; 
       case 401: 
        loginFail(); 
        break; 
       default: 
        loginFail(); 
      } 
     } 
    }; 

И в моем networklogic классе:

Call<Username> call = apiService.login(userObject); 
    call.enqueue(new Callback<Username>() { 
     @Override 
     public void onResponse(Call<Username> call, Response<Username> response) { 
      Log.d(TAG, "Responsecode: " + response.code()); 
      Message msg = handler.obtainMessage(response.code()); 
      msg.sendToTarget(); 

     } 

     @Override 
     public void onFailure(Call<Username> call, Throwable t) { 
      Log.d(TAG, "Failed: " + t.getMessage()); 
      Message msg = handler.obtainMessage(0); //0 for errors 
      msg.sendToTarget(); 
     } 
} 

Так как это выполняется на mainLooper, я могу играть с моим UI в любой из этих функций. Это должен быть правильный ответ.

0

Retrofit onResponse работает над потоком пользовательского интерфейса, поэтому ваш thread.sleep() создаст проблему для вас.

Thread.sleep(2000); //This line must not be on UI thread. 

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

+0

Удаление thread.sleep по-прежнему вызывает проблемы с моим login_button.setEnabled (true). Ошибка: android.util.AndroidRuntimeException: аниматоры могут запускаться только в потоках Looper –

+0

, пожалуйста, отправьте полную статистику стека. – Neo

+0

https://github.com/mathieudevos/pinkiponki-app/blob/master/PinkiPonki/app/src/main/java/com/mattikettu/pinkiponki/LoginActivity.java Код ошибки (с неправильным назначением пароля): http://pastebin.com/YHcxYy26 –

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

  • Нет связанных вопросов^_^