Android静态模型总是返回null
我当前正在使用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;
}
}
你把在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);
}
请注意,如果你使用一个信号量,你需要在失败时释放它。
你能举一个例子说明在这种情况下如何使用锁定吗?这是否像调用countdownlatchsignal? –
为什么要使用HttpClient而不是HttpUrlCOnnection?另外,使用静态方法被认为是糟糕的编程习惯。 – Christine
这是一个异步调用? –
@Christine我会说使用静态方法*不恰当*是一个糟糕的编程习惯。 –