Search code examples
javaandroidandroid-volleyfinal

Final object losing attribute value after function call


I am trying to properly handle Volley responses in my Android application, which loads some items from a database. Volley functions are encapsulated in the WebRequester class:

public class WebRequester extends Application {
    public static final String TAG = WebRequester.class.getSimpleName();

    private RequestQueue mRequestQueue;
    private static WebRequester mInstance;

    public WebRequester() {
        mInstance = this;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }

    public static synchronized WebRequester getInstance() {
        return mInstance;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    /* ... */
}

Another class, ItemsController, centralizes the requests to be created. In order to get the response code, I created a nested class, VolleyCallback, and set its attribute responseCode inside an overriden parseNetworkResponse() call:

public class FeedItemsController extends Application {
    private String URL_GET_FEED_ITEMS = /* My URL */; 
    private static final String TAG = FeedItemsController.class.getSimpleName();

    private ArrayList<FeedItem> feedItems;

    public class VolleyRequestCallback {
        public int responseCode;

        public int getResponseCode() {
            return responseCode;
        }

        public void setResponseCode(int responseCode) {
            this.responseCode = responseCode;
        }
    }

    public void loadItems() {
        final VolleyRequestCallback callback = new VolleyRequestCallback();

        if (feedItems == null) {
            feedItems = new ArrayList<>();

            Cache cache = WebRequester.getInstance().getRequestQueue().getCache();
            Cache.Entry entry = cache.get(URL_GET_FEED_ITEMS);

            if (entry != null) {
                try {
                    String data = new String(entry.data, "UTF-8");
                    parseJsonFeed(new JSONObject(data));
                } catch (JSONException | IOException e) {
                    e.printStackTrace();
                }
            }
            else {
                JsonObjectRequest jsonReq = new JsonObjectRequest(Request.Method.GET, URL_GET_FEED_ITEMS, null,
                        new Response.Listener<JSONObject>() {
                            @Override
                            public void onResponse(JSONObject response) {
                                VolleyLog.d(TAG, "Response: " + response.toString());
                                parseJsonFeed(response);
                            }
                        },
                        new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                VolleyLog.d(TAG, "Error: " + error.getMessage());
                            }
                         }
                ) {
                    @Override
                    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                        callback.setResponseCode(response.statusCode);
                        System.out.println("Code 1 = " + response.statusCode); 
                        return super.parseNetworkResponse(response);
                    }
                };

                WebRequester.getInstance().addToRequestQueue(jsonReq);
            }
        }
        System.out.println("Code 2 = " + callback.getResponseCode());
    }

    /* ... */
}

Then method loadItems() is called from another class. The issue is - when it enters the parseNetworkResponse() method, the resultCode is correctly set to, let's say, 200. However, when I try to reuse it outside the request overriding, it's 0 again:

Code 1 = 200
Code 2 = 0

It might be a bad implementation of a response handling, but my main question is why is the object attribute changed?

Thanks in advance


Solution

  • It turned out to be a not exciting bug. The call to parseNetworkResponse is asynchronous, meaning that when the first print is performed, the server had not responded yet.