2015-10-16 113 views
0

我當前正在使用AsynchttpClient向Web服務器發出POST請求。當我調試時,我可以清楚地看到正在返回的JSON。但是,當我將該變量設置爲ECUser類中的靜態方法時,我總是得到ECUser.getCurrentUser()爲空,這應該是不正確的。由於ECUser中的所有方法都是靜態的,所以我沒有看到我的問題是什麼。Android靜態模型總是返回null

如果我嘗試將jsonobject分配給來自asynchttpclient調用的responseBody,會發生同樣的情況。在匿名類終止之後,由於某種原因,jsonobject始終爲空。

private void attemptLogin(){ 
     RequestParams params = new RequestParams(); 
     params.put("email", userEmail.getText().toString()); 
     params.put("password", userPass.getText().toString()); 
     ECApiManager.post(Constants.loginAPI, params, new JsonHttpResponseHandler() { 
      @Override 
      public void onSuccess(int statusCode, Header[] headers, JSONObject responseBody) { 
       //called when response code 200 
       try{ 
        ECUser.setCurrentUser(new ECUser(responseBody)); 
        Log.d("login", responseBody.toString()); 
       }catch(JSONException e){ 
        e.printStackTrace(); 
       } 

      } 

     }); 

     if (ECUser.getCurrentUser() == null) { 
      ((OnLoginListener) getActivity()).loginSuccessful(false); 
     } 

這是我的ECUser類。

public class ECUser { 


    private static ECUser currentUser; 
    private static String userToken; 
    private String firstName; 
    private String lastName; 
    private static String userID; 
    private JSONObject jObject; 
    private boolean loginSuccess; 


    public ECUser(JSONObject data) throws JSONException { 
     this.jObject = data; 
     try { 
      this.loginSuccess = Boolean.parseBoolean(this.jObject.getString("success")); 
      if (this.loginSuccess) { 
       this.userToken = this.jObject.getString("token"); 
       this.firstName = this.jObject.getJSONObject("user").getString("firstname"); 
       this.lastName = this.jObject.getJSONObject("user").getString("lastname"); 
       this.userID = this.jObject.getJSONObject("user").getString("id"); 
      } 


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

    /** 
    * Method that refreshes the state of the current user by calling the API again. 
    */ 
    public static void refreshCurrentUser() { 
     RequestParams params = new RequestParams(); 
     params.put("token", userToken); 
     //Gotta put in user ID too. 
     params.put("user_id", userID); 
     // TODO: This should only call https://edu.chat/api/user, @JACOB 
     ECApiManager.get(Constants.refreshUserAPI, params, new JsonHttpResponseHandler() { 
      @Override 
      public void onSuccess(int statusCode, Header[] headers, JSONObject responseBody) { 

       try { 
        ECUser.setCurrentUser(new ECUser(responseBody)); 

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

     }); 
    } 

    // Static 

    public static ECUser getCurrentUser() { 
     return ECUser.currentUser; 
    } 

    public static void setCurrentUser(ECUser user) {ECUser.currentUser = user;} 

    public static String getUserToken() { 
     return ECUser.userToken; 
    } 

    // Dynamic 

    public String getLastName() { 
     return this.lastName; 
    } 

    public String getFirstName() { 
     return this.firstName; 
    } 

    public boolean getLoginSuccessful() { 
     return this.loginSuccess; 
    } 


} 
+0

爲什麼要使用HttpClient而不是HttpUrlCOnnection?另外,使用靜態方法被認爲是糟糕的編程習慣。 – Christine

+0

這是一個異步調用? –

+0

@Christine我會說使用靜態方法*不恰當*是一個糟糕的編程習慣。 –

回答

1

你把在ECApiManager#post登錄嘗試作爲同步方法,例如一旦嘗試完成就返回。所以,在調用post之後,您檢查當前用戶。

但是,顯然從http客戶端的名稱(AsynchttpClient)您可以理解該帖子是異步調用,這意味着HTTP請求將在後臺執行,並且一旦成功完成,它會調用您的JsonHttpResponseHandler#onSuccess方法。這意味着雖然ECApiManager#post將立即返回,但當前用戶尚未設置。

在異步模式下編程時,您需要處理髮生的事件,而不是隻按順序調用所有事件。如果您希望使其同步,則需要使用同步http客戶端(例如HttpClient或HttpUrlConnection),或者添加Semaphore以等待您的HTTP請求完成。

例如:

private void attemptLogin(){ 
    Semaphore sema = Semaphore(1); 
    sema.acquire(); 
    // .... 
    ECApiManager.post(Constants.loginAPI, params, new JsonHttpResponseHandler() { 
     @Override 
     public void onSuccess(int statusCode, Header[] headers, JSONObject responseBody) { 
      //called when response code 200 
      try{ 
       ECUser.setCurrentUser(new ECUser(responseBody)); 
       Log.d("login", responseBody.toString()); 
      }catch(JSONException e){ 
       e.printStackTrace(); 
      } 
      finally { 
       sema.release(); 
      } 
     } 

    }); 
    sema.acquire(); 
    if (ECUser.getCurrentUser() == null) { 
     ((OnLoginListener) getActivity()).loginSuccessful(false); 
    } 

請注意,如果你使用一個信號量,你需要在失敗時釋放它。

+0

你能舉一個例子說明在這種情況下如何使用鎖定嗎?這是否像調用countdownlatchsignal? –