I am doing the network operation in a model and then return the result, but the arraylist size is zero when I return it but inside the onResponse
method the arraylist size is not zero. How to resolve this?
public class doInBackground {
//i have initialized the arraylist here
ArrayList<Contact> arrayList=new ArrayList<>();
String url="http://192.168.10.3/volley/allUser.php";
private Context context;
public doInBackground(Context context){
this.context=context;
}
public ArrayList<Contact> getArrayList(){
JsonArrayRequest jsonArrayRequest=new JsonArrayRequest(Request.Method.POST, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
for(int i=0;i<response.length();i++){
try {
JSONObject jsonObject=response.getJSONObject(i);
Contact contact=new Contact();
contact.setName(jsonObject.getString("name"));
contact.setUserName(jsonObject.getString("username"));
arrayList.add(contact);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(context,e.toString(),Toast.LENGTH_LONG).show();
}
}
//outside the for loop the arraylist have data( i.e fetch from Mysql database)
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context,error.toString(),Toast.LENGTH_LONG).show();
}
});
Toast.makeText(context,arrayList.size()+"",Toast.LENGTH_LONG).show();
//using singleton design pattern to add the request to the queue MySingleton.getInstance(context).addToRequestQueue(jsonArrayRequest);
// here the arraylist is empty
return arrayList;
}
}
It is tipical not understanding async operations, Listener which You have given to Volley is waiting for response and Your
return
statement is called not when response returns from server side, but is called instantly. It means YourarrayList
is just empty ( code which fills it is running after response come back ). It must be async operations because if not all UI thread for user would just stop and Your application would not respond for any user action.So to fix this problem You need to wait until response will return and then after filling array call next wanted flow. Good is to add some loader view, show it before starting of request and hide after end of request.
Maybe some flow comparission.
Current flow:
Wanted flow:
EDIT ( about loader )
For loading can be used any view ( for example simple view with image ) by using view properties like VISIBILITY, so when loader view should be visible just call
loaderView.setVisibility(View.VISIBLE)
and when should be hidden -loaderView.setVisibility(View.GONE)
.To this purpose also can be used one of ready to use android libraries like ContentLoadingProgressBar.
Example usage of ContentLoadingProgressBar.
First add it to layout:
Next in Activity find it by:
And last just use it, for showing
loader.show()
, for hiddingloader.hide()
. So back to main point - show before request, hide inside in response listener.