I'm trying to run every minute a refresh for the UI. I wrote this code where I have an handler and a runnable with postdelay. Inside my runnable I have a call for a function that is returning a Map object. But every time, my runnable continues to the next lines of code before getting back the Map object from the function.
Does anyone know how to fix that? Itay.
My Code:
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
Map<String, String> varList = refreshVars(firstname, lastname, id);
String newlastdate = varList.get("newlastdate");
String newcurrentdate = varList.get("newcurrentdate");
/*UI changes related to "newlastdate" and "newcurrentdate"*/
}
handler.postDelayed(this, 60000);
}
};
handler.postDelayed(runnable, 60000);
The Function:
public Map<String, String> refreshExitVars(final String FN, final String LN, final String IDN){
final Map<String, String> list = new HashMap<>();
Response.Listener<String> responseListener = new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
boolean success = jsonResponse.getBoolean("success");
if (success) {
String nlastdate = jsonResponse.getString("date");
String ncurrentdate = jsonResponse.getString("currentdate");
list.put("newlastdate", nlastdate);
list.put("newcurrentdate", ncurrentdate);
} else {
int ErrorCode = jsonResponse.getInt("errorcode");
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(Exit.this);
builder.setMessage("" + ErrorCode)
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
this.finish();
}
})
.create()
.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
RequestUIChanges requestUIChanges = new RequestUIChanges(FN, LN, IDN, responseListener);
RequestQueue queue = Volley.newRequestQueue(Exit.this);
queue.add(requestUIChanges);
return list;
}
Arunavh Krishnan
Software Engineer
The problem is with the asynchronous nature of the request.
After you make the request, you don't wait for the response. The code continues to run (this is an asynchronous piece of code).
When the request is finally processed, you get your response in onResponse method. But this piece of code was non-blocking. It means it doesn't guarantee that onResponse will be called before you return the list. You have already returned the list (* which is a map not list) from the function refershExitVars and at that point of time onResponse wasn't even called and hence your map is empty.
Solution : You cannot simply return values from a non-blocking method. You need a Callback.
When you call refreshExitVars you need to pass it a Callback. Once onResponse is called and you have your map ready (not empty), you can use this Callback to transfer your map data back to the caller.