2016-06-16 11 views
-2

我正在製作一個簡單的材料設計登錄屏幕,該屏幕在改造獲取數據時顯示進度對話框。使用UI線程改造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(NWL)類:

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:動畫師只可在環線上運行(約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跑,我可以玩我的任何這些功能的用戶界面。 這應該是正確的答案。

0

改進onResponse適用於UI線程,所以你的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 –