Usage of Volley in Android (10) awareness of Request and Reponse

Source: Internet
Author: User

We know that in the network Http Communication, there must be a Request. Similarly, there must be a Response. Before we use RequestQueue in Volley to add a Request, you must first create a Request object, such as StringRequest, JsonObjectRequest, and ImageRequest. The following are JsonRequest and ImageRequest in the previous Demo:

JsonObjectRequest:

    public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener,            ErrorListener errorListener) {

ImageRequest:

    public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight,            Config decodeConfig, Response.ErrorListener errorListener) 

Volley provides a basic Request abstract class, as follows:

public abstract class Request<T> implements Comparable<Request<T>> {

This class defines some basic parameter variables in the request, such

Method:

    /**     * Request method of this request.  Currently supports GET, POST, PUT, DELETE, HEAD, OPTIONS,     * TRACE, and PATCH.     */    private final int mMethod;
The value is as follows:

    /**     * Supported request methods.     */    public interface Method {        int DEPRECATED_GET_OR_POST = -1;        int GET = 0;        int POST = 1;        int PUT = 2;        int DELETE = 3;        int HEAD = 4;        int OPTIONS = 5;        int TRACE = 6;        int PATCH = 7;    }

Url in the request:

    /** URL of this request. */    private final String mUrl;

An ErroListener,

    /** Listener interface for errors. */    private final Response.ErrorListener mErrorListener;

There are other parameters, such as shouldCache (whether cache is required) and tag (classification tag). The following two abstract methods are provided in the Request, which must be implemented by sub-classes:

    /**     * Subclasses must implement this to parse the raw network response     * and return an appropriate response type. This method will be     * called from a worker thread.  The response will not be delivered     * if you return null.     * @param response Response from the network     * @return The parsed response, or null in the case of an error     */    abstract protected Response<T> parseNetworkResponse(NetworkResponse response);

    /**     * Subclasses must implement this to perform delivery of the parsed     * response to their listeners.  The given response is guaranteed to     * be non-null; responses that fail to parse are not delivered.     * @param response The parsed response returned by     * {@link #parseNetworkResponse(NetworkResponse)}     */    abstract protected void deliverResponse(T response);

Each subclass must implement two methods,

1) parseNetworkResponse

How to parse the corresponding Request when obtaining the Response from the network is analyzed by the corresponding Request, such as in JsonObjectRequest:

    @Override    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {        try {            String jsonString =                new String(response.data, HttpHeaderParser.parseCharset(response.headers));            return Response.success(new JSONObject(jsonString),                    HttpHeaderParser.parseCacheHeaders(response));        } catch (UnsupportedEncodingException e) {            return Response.error(new ParseError(e));        } catch (JSONException je) {            return Response.error(new ParseError(je));        }    }

For example, in ImageRequest:

    @Override    protected Response<Bitmap> parseNetworkResponse(NetworkResponse response) {        // Serialize all decode on a global lock to reduce concurrent heap usage.        synchronized (sDecodeLock) {            try {                return doParse(response);            } catch (OutOfMemoryError e) {                VolleyLog.e("Caught OOM for %d byte image, url=%s", response.data.length, getUrl());                return Response.error(new ParseError(e));            }        }    }

In doParse, the image is actually processed as follows:

    private Response<Bitmap> doParse(NetworkResponse response) {        byte[] data = response.data;        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();        Bitmap bitmap = null;        if (mMaxWidth == 0 && mMaxHeight == 0) {            decodeOptions.inPreferredConfig = mDecodeConfig;            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);        } else {            // If we have to resize this image, first get the natural bounds.            decodeOptions.inJustDecodeBounds = true;            BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            int actualWidth = decodeOptions.outWidth;            int actualHeight = decodeOptions.outHeight;            // Then compute the dimensions we would ideally like to decode to.            int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,                    actualWidth, actualHeight);            int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,                    actualHeight, actualWidth);            // Decode to the nearest power of two scaling factor.            decodeOptions.inJustDecodeBounds = false;            // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it?            // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;            decodeOptions.inSampleSize =                findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);            Bitmap tempBitmap =                BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            // If necessary, scale down to the maximal acceptable size.            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth ||                    tempBitmap.getHeight() > desiredHeight)) {                bitmap = Bitmap.createScaledBitmap(tempBitmap,                        desiredWidth, desiredHeight, true);                tempBitmap.recycle();            } else {                bitmap = tempBitmap;            }        }        if (bitmap == null) {            return Response.error(new ParseError(response));        } else {            return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response));        }    }

Therefore, if we customize a Request, we need to implement our own logic. For example, if we get a video, we will decode the data.

In the above method implementation, we can see that at last, a Response object is returned through the Response. success Method, and how is this Response object used? It depends on the deliverResponse method below.

2) deliverResponse

In the NetworkDispatcher thread, a Reponse object is returned after the data is obtained from the network and parsed by the requested parseNetworkResponse method, the Executor will be called to post the request back to the main thread, as follows:

mDelivery.postResponse(request, response);

The postResponse method in mDelivery is actually a new thread to call the Request's deliverResponse method. In the ExecutorDelivery class:

public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {        request.markDelivered();        request.addMarker("post-response");        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));    }

In the run method of the ResponseDeliveryRunnable class, we can see:

            // Deliver a normal response or error, depending.            if (mResponse.isSuccess()) {                mRequest.deliverResponse(mResponse.result);            } else {                mRequest.deliverError(mResponse.error);            }

Let's take a look at the deliverResponse method in StringRequest and ImageRequest:

private final Response.Listener<Bitmap> mListener;...@Override    protected void deliverResponse(Bitmap response) {        mListener.onResponse(response);    }
We can see that all of them call a Response. the onResponse method of the Listener class. In fact, this Listener is implemented when we create a request and is passed in. For example, when we create JsonObjectRequest and ImageRequest in the previous Demo:

ImageRequest imgRequest = new ImageRequest(imgUrl,new Response.Listener<Bitmap>() {@Overridepublic void onResponse(Bitmap arg0) {// TODO Auto-generated method stubimageView.setImageBitmap(arg0);}}, 100, 100, Config.ARGB_8888, new ErrorListener() {@Overridepublic void onErrorResponse(VolleyError arg0) {imageView.setImageResource(R.drawable.ic_launcher);}});

As shown in the above implementation in the new Reponse. Listener method, it is clear that the reason for doing so is that only the caller knows how to process the data parsed by the Request.

From here, we can also know that in the Reponse class, such an interface will be defined, as follows, is the definition of the Response class in Volley:

public class Response<T> {    /** Callback interface for delivering parsed responses. */    public interface Listener<T> {        /** Called when a response is received. */        public void onResponse(T response);    }

Besides the definition of this interface, the definition of an ErrorListener interface is not listed. In addition, the Response class stores information such as CacheEntry, which is relatively simple because the Listener interface is defined.

Now, let's summarize:

1) when creating a Request, a Response. Listener will be set as a Request parameter variable, and then the add method of RequestQueue will be called to add it to the Queue.

2) requests in the Queue will be communicated with the network by NetworkDispatcher (if there is a cache, It is CacheDispatcher ).

3) when the Request result is returned, the Request first calls the parseNetworkResponse Method for different processing based on different Request types, such as Json and Image.

4) after the Request is analyzed, the returned Reponse object will start a new thread in the ResponseDelivery class and call the Listener in step 1 to process it.

End.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.