2013년 10월 29일 화요일

Google Volley - Features and Code Tutorial (Complete Walkthrough)


Main Features and Advantages of Volley

* one requestQueue takes in all the requests 
     -grants parallel requests

* Priority settings for requests
     -image gets low priority by default
     -you can extend Priority class to customize priority

* Cancel Request Features ( for cases like when a user is scrolling fast with a lot of views in a listview )
      -done automatically

* Solves android Froyo bugs for HttpURLConnection


* NetworkImageView

     -imageLoader
     -image loading lets request sit in the queue for a while then creates a batch of requests
     -image caching
     -image scaling
     -Parallel Bitmap loading = Number of Cores

Let's see how volley actually works internally.

     



When you create a request and put it into a queue, it is added to the cache queue.
Then when the given request is taken out from the queue by CacheDispatcher,
volley checks cache of the app to see if it can fetch the result solely from cache.
If it can, it is a Cache-Hit, otherwise it is a Cache-Miss.

In case of cache-hit, it simply reads response from cache and parse the response.

In case of cache-miss, the request is dequed by NetworkDispatcher, and sends HttpRequest 

Code Guide
Implementing volley basically consists of 3 steps:
1. creating instance of requestQueue
2. creating request
3. inserting request into the requestQueue

1. Create Volley Singleton
Like I mentioned above, Volley handles all the requests with a Single Queue. So, it is best to instantiate request queue only once using Singleton Pattern.


public class VolleySingleton {
    private static VolleySingleton mInstance = null;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;

    private VolleySingleton(Context context){
        mRequestQueue = Volley.newRequestQueue(context);
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache mCache = new LruCache(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
    }

    public static VolleySingleton getInstance(Context context){
        if(mInstance == null){
            mInstance = new VolleySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        return this.mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return this.mImageLoader;
    }
}

2. Define Http Requests
1)Pre-defined Requests
takes int Request.Method.(GET or POST), String url, T Content, Response Listener, Response ErrorListener
new JsonObjectRequest( //JsonArrayRequest and StringRequest(call API in URI) is the same
                Request.Method.POST, "url", null,
                new Response.Listener() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {

                    }
                }
        );
    };
2)Custom Reqeusts (JsonRequest or Request) needs parsing.
      1 - JsonRequest needs to parse the received networkresponse into the given result type in parseNetworkResponse method

    JsonRequest jsonRequest = new JsonRequest(Request.Method.POST, "url", "requestBody",
            new Response.Listener() {
                @Override
                public void onResponse(JSONArray jsonArray) {

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {

                }
            })
    {
        @Override
        protected Response parseNetworkResponse(NetworkResponse networkResponse) {
            try{
                String json = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers));
                return Response.success(
                        new JSONArray(json), HttpHeaderParser.parseCacheHeaders(networkResponse)
                );
            }
            catch(UnsupportedEncodingException e){
                return Response.error(new ParseError(e));
            }
            catch(JSONException e){
                return Response.error(new ParseError(e));
            }
        }
    };
-A Request class object needs to parse the received NetworkResponse in parsenetworkResponse method, as well as delivering response to the listener through the method deliverResponse(T t)
    Request integerRequest = new Request(Request.Method.POST, "url", new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {

        }
    }) {
        @Override
        protected Response parseNetworkResponse(NetworkResponse networkResponse) {
            try {
                Integer i = new Integer(new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers)));
                return Response.success(i, HttpHeaderParser.parseCacheHeaders(networkResponse));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void deliverResponse(Integer integer) {
             listener.onResponse(integer);
        }
    };
3) Image Requests Use ImageLoader defined in VollySingleton
    ImageRequest a = new ImageRequest("url", new Response.Listener() {
        @Override
        public void onResponse(Bitmap bitmap) {

        }
    }, /*maxWidth*/0, /*maxHeight*/ 0, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
        }
    });
Or in XML
    mImageView.setImageUrl(BaseUrl+ item.image_url, mImageLoader);
(Automatically added into queue)

3. Add Request to Queue
VolleySingleton.getInstance(mContext).getRequstQueue().add(request);


Resources:
     Youtube - Google I/O 2013 - Volley: Easy, Fast Networking for Android
                    http://www.youtube.com/watch?v=yhv8l9F44qo
     Setting up the Android Google Volley ImageLoader for NetworkImageView
          http://cypressnorth.com/mobile-application-development/setting-android-google-volley-imageloader-networkimageview/ 
     [android] Volley - Network & ImageLoading 라이브러리 ( google I/O 2013 )     
          http://hanburn.tistory.com/135