Initialize ArrayList to ArrayList obtained asynchronously

Vasko Vasilev :

I am trying to create a new ArrayList instance and initialize it to an arraylist returned by a function. The things I have tried so far do not work.

This is my function which is supposed to return an ArrayList of type . I have tested it and it works perfectly, the contents are read successfully and are stored in the temporary ArrayList created within the function. After filling this ArrayList the function will return it.

public ArrayList<User> fetchAllUsers() {

   final ArrayList<User> allUsers = new ArrayList<>();

    RequestQueue requestQueue = Volley.newRequestQueue(this);
    JsonArrayRequest arrayRequest = new JsonArrayRequest(
            Request.Method.GET,
            "http://ecoproduce.eu/api/User",
            null,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.e("Rest response", response.toString());

                    Gson gson = new Gson();
                    User user = new User();

                    for (int i = 0; i < response.length(); i++) {
                        try {
                            user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        allUsers.add(user);
                    }

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Error response", error.toString());
                }
            }
    );
    requestQueue.add(arrayRequest);
    return allUsers;
}

The problem I face is when I try to declare a new arrayList instance and I try to fill it with the ArrayList returned from the function.

I have tried doing this in the following ways:

Initialize the newly created instance through the constructor:

ArrayList<User> allUsers = new ArrayList<User>(fetchAllUsers()); 

Initialize the newly created instace of ArrayList through the addAll() function

ArrayList<User> allUsers = new ArrayList<User>();
allUsers.addAll(fetchAllUsers());

Both of these attempts have left me with an empty ArrayList, how can I solve this?

SOLUTION:

Implemented an interface

public interface VolleyCallBack {
    ArrayList<User> onSuccess();
}

Changes to the getAllUsers function

 public ArrayList<User> getAllUsers(final String email, final VolleyCallBack callBack) {


    requestQueue = Volley.newRequestQueue(this);
    JsonArrayRequest arrayRequest = new JsonArrayRequest(
            Request.Method.GET,
            "http://ecoproduce.eu/api/User",
            null,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.e("Rest response", response.toString());

                    Gson gson = new Gson();
                    User user = new User();

                    for (int i = 0; i < response.length(); i++) {
                        try {
                            user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        allUsers.add(user);
                    }
                    /*for (int i = 0; i < allUsers.size(); i++) {
                        if (allUsers.get(i).getEmail().compareTo(email) == 0) {
                            checkSucesfull = true;
                        }

                    }*/
                    callBack.onSuccess();
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Error response", error.toString());
                }
            }
    );
    requestQueue.add(arrayRequest);
    return allUsers;
}

How I call the function now

allUsers = getAllUsers(email, new VolleyCallBack() {
                    @Override
                    public ArrayList<User> onSuccess() {
                        return allUsers;
                    }
                });

And the allUsers ArrayList is made global (which is probably not the best solution).

I am still open to improvements on this.

vikas kumar :

What I am getting is you are making an asynchronous call to get the list items. which will come sometime later but the initialization will happen as soon as the function gets called. Your ArrayList is in synchronous and the method fetchAllUsers() calls for an API to in background thread to fill the items in ArrayList but returns an empty list instantly that's why you are getting empty list.

So in actual you can't initialize some ArrayList which depends on the background thread. you can use callbacks to get the data later but not instantly i hope you are getting my point.

Now what to do: Depends on what you are trying to achieve but just return nothing from fetchAllUsers and on callback of api call do whatever you want to do

   public void fetchAllUsers() {
    final ArrayList<User> allUsers = new ArrayList<>();
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    JsonArrayRequest arrayRequest = new JsonArrayRequest(
            Request.Method.GET,
            "http://ecoproduce.eu/api/User",
            null,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.e("Rest response", response.toString());

                    Gson gson = new Gson();
                    User user = new User();

                    for (int i = 0; i < response.length(); i++) {
                        try {
                            user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        allUsers.add(user);
                    }
                   //here your list items are ready to be used, so call some function to consume it 
                  //TODO call to further function
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Error response", error.toString());
                }
            }
    );
    requestQueue.add(arrayRequest);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=23292&siteId=1