nohttp/src/main/java/com/yanzhenjie/nohttp/rest/StringRequest.java
public class StringRequest extends Request<String> {

    public StringRequest(String url) {
        this(url, RequestMethod.GET);
    }

    public StringRequest(String url, RequestMethod requestMethod) {
        super(url, requestMethod);
    }

    @Override
    public String parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception {
        return parseResponseString(responseHeaders, responseBody);
    }

    /**
     * Parse http response to string.
     *
     * @param responseHeaders header from http response.
     * @param responseBody    byteArray from http response.
     * @return result fro response.
     */
    public static String parseResponseString(Headers responseHeaders, byte[] responseBody) {
        if (responseBody == null || responseBody.length == 0)
            return "";
        String charset = HeaderUtils.parseHeadValue(responseHeaders.getContentType(), "charset", "");
        return IOUtils.toString(responseBody, charset);
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/download/DownloadRequest.java
public class DownloadRequest extends BasicRequest<DownloadRequest> {
    /**
     * Also didn't download to start download again.
     */
    public static final int STATUS_RESTART = 0;
    /**
     * Part has been downloaded, continue to download last time.
     */
    public static final int STATUS_RESUME = 1;
    /**
     * Has the download is complete, not to download operation.
     */
    public static final int STATUS_FINISH = 2;

    /**
     * File the target folder.
     */
    private final String mFileDir;
    /**
     * The file target name.
     */
    private final String mFileName;
    /**
     * If is to download a file, whether the breakpoint continuing.
     */
    private final boolean isRange;
    /**
     * If there is a old files, whether to delete the old files.
     */
    private final boolean isDeleteOld;

    /**
     * Create download handle.
     *
     * @param url           url.
     * @param requestMethod {@link RequestMethod}.
     * @param fileFolder    file save folder.
     * @param isDeleteOld   find the same when the file is deleted after download, or on behalf of the download is
     *                      complete, not to handle the network.
     * @see #DownloadRequest(String, RequestMethod, String, String, boolean, boolean)
     */
    public DownloadRequest(String url, RequestMethod requestMethod, String fileFolder, boolean isRange, boolean isDeleteOld) {
        this(url, requestMethod, fileFolder, null, isRange, isDeleteOld);
    }

    /**
     * Create a download object.
     *
     * @param url           download address.
     * @param requestMethod {@link RequestMethod}.
     * @param fileFolder    folder to save file.
     * @param filename      filename.
     * @param isRange       whether the breakpoint continuing.
     * @param isDeleteOld   find the same when the file is deleted after download, or on behalf of the download is
     *                      complete, not to handle the network.
     * @see #DownloadRequest(String, RequestMethod, String, boolean, boolean)
     */
    public DownloadRequest(String url, RequestMethod requestMethod, String fileFolder, String filename, boolean isRange, boolean isDeleteOld) {
        super(url, requestMethod);
        this.mFileDir = fileFolder;
        this.mFileName = filename;
        this.isRange = isRange;
        this.isDeleteOld = isDeleteOld;
    }

    /**
     * Return the mFileDir.
     *
     * @return it won't be empty.
     */
    public String getFileDir() {
        return this.mFileDir;
    }

    /**
     * Return the mFileName.
     *
     * @return it won't be empty.
     */
    public String getFileName() {
        return this.mFileName;
    }

    /**
     * Return the isRange.
     *
     * @return true: breakpoint continuing, false: don't need a breakpoint continuing.
     */
    public boolean isRange() {
        return this.isRange;
    }

    /**
     * If there is a old files, whether to delete the old files.
     *
     * @return true: deleted, false: don't delete.
     */
    public boolean isDeleteOld() {
        return this.isDeleteOld;
    }

    /**
     * <p>
     * Query before download status {@link #STATUS_RESTART} representative no download do to download again; Download
     * {@link #STATUS_RESUME} represents a part of, to continue to download; {@link #STATUS_FINISH} representatives
     * have finished downloading.
     * </p>
     *
     * @return int value, compared with the {@value #STATUS_RESTART}, {@value #STATUS_RESUME}, {@value #STATUS_FINISH}.
     * @see #STATUS_RESTART
     * @see #STATUS_RESUME
     * @see #STATUS_FINISH
     */
    public int checkBeforeStatus() {
        if (this.isRange) {
            try {
                File lastFile = new File(mFileDir, mFileName);
                if (lastFile.exists() && !isDeleteOld)
                    return STATUS_FINISH;
                File tempFile = new File(mFileDir, mFileName + ".nohttp");
                if (tempFile.exists())
                    return STATUS_RESUME;
            } catch (Exception ignored) {
            }
        }
        return STATUS_RESTART;
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/JsonObjectRequest.java
public class JsonObjectRequest extends Request<JSONObject> {

    public JsonObjectRequest(String url) {
        this(url, RequestMethod.GET);
    }

    public JsonObjectRequest(String url, RequestMethod requestMethod) {
        super(url, requestMethod);
        setAccept(Headers.HEAD_VALUE_CONTENT_TYPE_JSON);
    }

    @Override
    public JSONObject parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception {
        String jsonStr = StringRequest.parseResponseString(responseHeaders, responseBody);
        return new JSONObject(jsonStr);
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/RequestQueue.java
public class RequestQueue {

    private AtomicInteger mInteger = new AtomicInteger(1);
    private final BlockingQueue<Work<? extends Request<?>, ?>> mQueue = new PriorityBlockingQueue<>();
    private final CancelerManager mCancelerManager = new CancelerManager();
    private RequestDispatcher[] mDispatchers;

    /**
     * @param threadPoolSize number of thread pool.
     */
    public RequestQueue(int threadPoolSize) {
        mDispatchers = new RequestDispatcher[threadPoolSize];
    }

    /**
     * All dispatcher in the boot queue, such as the dispatcher that has already been started in the queue,
     * will stop all dispatcher first and restart the equal number of dispatcher.
     *
     * @see #stop()
     */
    public void start() {
        stop();

        for (int i = 0; i < mDispatchers.length; i++) {
            RequestDispatcher dispatcher = new RequestDispatcher(mQueue);
            mDispatchers[i] = dispatcher;
            dispatcher.start();
        }
    }

    /**
     * Add a request to the queue.
     *
     * @param what the {@code what} be returned in the result callback.
     * @param request {@link Request}.
     * @param listener {@link OnResponseListener}.
     * @param <T> {@link T}.
     */
    public <T> void add(int what, final Request<T> request, OnResponseListener<T> listener) {
        Worker<? extends Request<T>, T> worker = new Worker<>(request);
        AsyncCallback<T> callback = new AsyncCallback<T>(listener) {
            @Override
            public void onFinish(int what) {
                mCancelerManager.removeCancel(request);
                super.onFinish(what);
            }
        };
        final Work<? extends Request<T>, T> work = new Work<>(worker, what, callback);
        work.setSequence(mInteger.incrementAndGet());

        callback.setQueue(mQueue);
        callback.setWork(work);

        request.setCancelable(work);

        mCancelerManager.addCancel(request, work);
        mQueue.add(work);
    }

    /**
     * @deprecated use {@link #unFinishSize()} instead.
     */
    @Deprecated
    public int size() {
        return unFinishSize();
    }

    /**
     * The number of requests that have not been executed yet.
     */
    public int unStartSize() {
        return mQueue.size();
    }

    /**
     * The number of all requests, including the request being executed.
     */
    public int unFinishSize() {
        return mCancelerManager.size();
    }

    /**
     * Cancel all requests and stop all dispatchers in the queue.
     */
    public void stop() {
        cancelAll();

        for (RequestDispatcher dispatcher : mDispatchers) {
            if (dispatcher != null) {
                dispatcher.quit();
            }
        }
    }

    /**
     * According to the sign to cancel a task.
     *
     * @see CancelerManager#cancel(Object)
     */
    public void cancelBySign(Object sign) {
        mCancelerManager.cancel(sign);
    }

    /**
     * Cancel all requests.
     */
    public void cancelAll() {
        mCancelerManager.cancelAll();
    }

    static class AsyncCallback<T>
      implements OnResponseListener<T> {

        private final OnResponseListener<T> mCallback;
        private BlockingQueue<Work<? extends Request<?>, ?>> mQueue;
        private Work<? extends Request<?>, ?> mWork;

        AsyncCallback(OnResponseListener<T> callback) {
            this.mCallback = callback;
        }

        public void setQueue(BlockingQueue<Work<? extends Request<?>, ?>> queue) {
            this.mQueue = queue;
        }

        public void setWork(Work<? extends Request<?>, ?> work) {
            this.mWork = work;
        }

        @Override
        public void onStart(final int what) {
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onStart(what);
                }
            });
        }

        @Override
        public void onSucceed(final int what, final Response<T> response) {
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onSucceed(what, response);
                }
            });
        }

        @Override
        public void onFailed(final int what, final Response<T> response) {
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onFailed(what, response);
                }
            });
        }

        @Override
        public void onFinish(final int what) {
            if (mQueue.contains(mWork)) {
                mQueue.remove(mWork);
            }

            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onFinish(what);
                }
            });
        }
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/SyncRequestExecutor.java
public enum SyncRequestExecutor {

    INSTANCE;

    private RequestHandler mRequestHandler;

    SyncRequestExecutor() {
        InitializationConfig initializationConfig = NoHttp.getInitializeConfig();
        mRequestHandler = new RequestHandler(
                initializationConfig.getCacheStore(),
                initializationConfig.getNetworkExecutor(),
                initializationConfig.getInterceptor()
        );
    }

    /**
     * Perform a handle.
     */
    public <T> Response<T> execute(Request<T> request) {
        return mRequestHandler.handle(request);
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/ImageRequest.java
public class ImageRequest extends Request<Bitmap> {

    private final int mMaxWidth;
    private final int mMaxHeight;
    private final Bitmap.Config mDecodeConfig;
    private ImageView.ScaleType mScaleType;

    /**
     * Decoding lock so that we don't decode more than one image at a time (to avoid OOM's).
     */
    private static final Object DECODE_LOCK = new Object();

    public ImageRequest(String url, RequestMethod requestMethod, int maxWidth, int maxHeight, Bitmap.Config
            decodeConfig, ImageView.ScaleType scaleType) {
        super(url, requestMethod);
        this.mMaxWidth = maxWidth;
        this.mMaxHeight = maxHeight;
        this.mDecodeConfig = decodeConfig;
        this.mScaleType = scaleType;
        setAccept("image/*");
    }

    @Override
    public Bitmap parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception {
        synchronized (DECODE_LOCK) {
            Bitmap bitmap = null;
            if (responseBody != null) {
                try {
                    bitmap = doResponse(responseBody);
                } catch (OutOfMemoryError e) {
                    String errorMessage = String.format(Locale.US, "Caught OOM for %d byte image, url=%s",
                            responseBody.length, url());
                    Logger.e(e, errorMessage);
                }
            }
            return bitmap;
        }
    }

    /**
     * The real guts of AnalyzeResponse. Broken out for readability.
     */
    private Bitmap doResponse(byte[] byteArray) throws OutOfMemoryError {
        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
        Bitmap bitmap;
        if (mMaxWidth == 0 && mMaxHeight == 0) {
            decodeOptions.inPreferredConfig = mDecodeConfig;
            bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);
        } else {
            decodeOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);
            int actualWidth = decodeOptions.outWidth;
            int actualHeight = decodeOptions.outHeight;

            int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, actualWidth, actualHeight, mScaleType);
            int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, actualHeight, actualWidth, mScaleType);

            decodeOptions.inJustDecodeBounds = false;
            decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);
            Bitmap tempBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);

            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() >
                    desiredHeight)) {
                bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
                tempBitmap.recycle();
            } else {
                bitmap = tempBitmap;
            }
        }
        return bitmap;
    }

    private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary,
                                           ImageView.ScaleType scaleType) {

        // If no dominant value at all, just return the actual.
        if ((maxPrimary == 0) && (maxSecondary == 0)) {
            return actualPrimary;
        }

        // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio.
        if (scaleType == ImageView.ScaleType.FIT_XY) {
            if (maxPrimary == 0) {
                return actualPrimary;
            }
            return maxPrimary;
        }

        // If primary is unspecified, scale primary to match secondary's scaling ratio.
        if (maxPrimary == 0) {
            double ratio = (double) maxSecondary / (double) actualSecondary;
            return (int) (actualPrimary * ratio);
        }

        if (maxSecondary == 0) {
            return maxPrimary;
        }

        double ratio = (double) actualSecondary / (double) actualPrimary;
        int resized = maxPrimary;

        // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio.
        if (scaleType == ImageView.ScaleType.CENTER_CROP) {
            if ((resized * ratio) < maxSecondary) {
                resized = (int) (maxSecondary / ratio);
            }
            return resized;
        }

        if ((resized * ratio) > maxSecondary) {
            resized = (int) (maxSecondary / ratio);
        }
        return resized;
    }

    // Visible for testing.
    public static int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        while ((n * 2) <= ratio) {
            n *= 2;
        }
        return (int) n;
    }

}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/Request.java
public abstract class Request<Result> extends BasicRequest<Request> {
    /**
     * Cache key.
     */
    private String mCacheKey;
    /**
     * If just read from cache.
     */
    private CacheMode mCacheMode = CacheMode.DEFAULT;

    /**
     * Create a handle, handle method is {@link RequestMethod#GET}.
     *
     * @param url handle address, like: http://www.nohttp.net.
     */
    public Request(String url) {
        this(url, RequestMethod.GET);
    }

    /**
     * Create a handle
     *
     * @param url           handle address, like: http://www.nohttp.net.
     * @param requestMethod handle method, like {@link RequestMethod#GET}, {@link RequestMethod#POST}.
     */
    public Request(String url, RequestMethod requestMethod) {
        super(url, requestMethod);
    }

    /**
     * Set the handle cache primary key, it should be globally unique.
     *
     * @param key unique key.
     */
    public Request setCacheKey(String key) {
        this.mCacheKey = key;
        return this;
    }

    /**
     * Get key of cache data.
     *
     * @return cache key.
     */
    public String getCacheKey() {
        return TextUtils.isEmpty(mCacheKey) ? url() : mCacheKey;
    }

    /**
     * Set the cache mode.
     *
     * @param cacheMode The value from {@link CacheMode}.
     */
    public Request setCacheMode(CacheMode cacheMode) {
        this.mCacheMode = cacheMode;
        return this;
    }

    /**
     * He got the handle cache mode.
     *
     * @return value from {@link CacheMode}.
     */
    public CacheMode getCacheMode() {
        return mCacheMode;
    }

    /**
     * Parse handle results for generic objects.
     *
     * @param responseHeaders response headers of server.
     * @param responseBody    response data of server.
     * @return your response result.
     * @throws Exception parse error.
     */
    public abstract Result parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception;

}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/JsonArrayRequest.java
public class JsonArrayRequest extends Request<JSONArray> {

    public JsonArrayRequest(String url) {
        this(url, RequestMethod.GET);
    }

    public JsonArrayRequest(String url, RequestMethod requestMethod) {
        super(url, requestMethod);
        setAccept(Headers.HEAD_VALUE_CONTENT_TYPE_JSON);
    }

    @Override
    public JSONArray parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception {
        String jsonStr = StringRequest.parseResponseString(responseHeaders, responseBody);
        return new JSONArray(jsonStr);
    }

}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/ByteArrayRequest.java
public class ByteArrayRequest extends Request<byte[]> {

    public ByteArrayRequest(String url) {
        this(url, RequestMethod.GET);
    }

    public ByteArrayRequest(String url, RequestMethod requestMethod) {
        super(url, requestMethod);
    }

    @Override
    public byte[] parseResponse(Headers responseHeaders, byte[] responseBody) throws Exception {
        return responseBody == null ? new byte[0] : responseBody;
    }
}
nohttp/src/main/java/com/yanzhenjie/nohttp/rest/Response.java
public interface Response<T> {

    /**
     * Get the Request.
     */
    Request<T> request();

    /**
     * Get the response code of handle.
     *
     * @return response code.
     */
    int responseCode();

    /**
     * Request is executed successfully.
     *
     * @return True: Succeed, false: failed.
     */
    boolean isSucceed();

    /**
     * Whether the data returned from the cache.
     *
     * @return True: the data from cache, false: the data from server.
     */
    boolean isFromCache();

    /**
     * Get http response headers.
     *
     * @return {@link Headers}.
     */
    Headers getHeaders();

    /**
     * Get handle results.
     *
     * @return {@link T}.
     */
    T get();

    /**
     * When the handle fail to getList the exception type.
     *
     * @return The exception.
     */
    Exception getException();

    /**
     * Gets the tag of handle.
     *
     * @return {@link Object}.
     */
    Object getTag();

    /**
     * Gets the millisecond of handle.
     *
     * @return {@link Long}.
     */
    long getNetworkMillis();
}
nohttp/src/main/java/com/yanzhenjie/nohttp/download/DownloadQueue.java
public class DownloadQueue {

    private AtomicInteger mInteger = new AtomicInteger(1);
    private final BlockingQueue<Work<? extends DownloadRequest>> mQueue = new PriorityBlockingQueue<>();
    private final CancelerManager mCancelerManager = new CancelerManager();
    private DownloadDispatcher[] mDispatchers;

    /**
     * @param threadPoolSize number of thread pool.
     */
    public DownloadQueue(int threadPoolSize) {
        mDispatchers = new DownloadDispatcher[threadPoolSize];
    }

    /**
     * All dispatcher in the boot queue, such as the dispatcher that has already been started in the queue,
     * will stop all dispatcher first and restart the equal number of dispatcher.
     *
     * @see #stop()
     */
    public void start() {
        stop();

        for (int i = 0; i < mDispatchers.length; i++) {
            DownloadDispatcher dispatcher = new DownloadDispatcher(mQueue);
            mDispatchers[i] = dispatcher;
            dispatcher.start();
        }
    }

    /**
     * Add a request to the queue.
     *
     * @param what the {@code what} be returned in the result callback.
     * @param request {@link DownloadRequest}
     * @param listener {@link DownloadListener}
     */
    public void add(int what, final DownloadRequest request, DownloadListener listener) {
        AsyncCallback callback = new AsyncCallback(listener);
        Worker<? extends DownloadRequest> worker = new Worker<>(what, request, callback);
        final Work<? extends DownloadRequest> work = new Work<>(worker, what, callback);
        work.setSequence(mInteger.incrementAndGet());

        callback.setQueue(mQueue);
        callback.setCancelerManager(mCancelerManager);
        callback.setWork(work);
        callback.setRequest(request);

        request.setCancelable(work);

        mCancelerManager.addCancel(request, work);
        mQueue.add(work);
    }

    /**
     * @deprecated use {@link #unFinishSize()} instead.
     */
    @Deprecated
    public int size() {
        return unFinishSize();
    }

    /**
     * The number of requests that have not been executed yet.
     */
    public int unStartSize() {
        return mQueue.size();
    }

    /**
     * The number of all requests, including the request being executed.
     */
    public int unFinishSize() {
        return mCancelerManager.size();
    }

    /**
     * Cancel all requests and stop all dispatchers in the queue.
     */
    public void stop() {
        cancelAll();

        for (DownloadDispatcher dispatcher : mDispatchers) {
            if (dispatcher != null) {
                dispatcher.quit();
            }
        }
    }

    /**
     * According to the sign to cancel a task.
     *
     * @see CancelerManager#cancel(Object)
     */
    public void cancelBySign(Object sign) {
        mCancelerManager.cancel(sign);
    }

    /**
     * Cancel all requests.
     */
    public void cancelAll() {
        mCancelerManager.cancelAll();
    }

    private static class AsyncCallback
      implements DownloadListener {

        private final DownloadListener mCallback;
        private BlockingQueue<Work<? extends DownloadRequest>> mQueue;
        private Work<? extends DownloadRequest> mWork;
        private CancelerManager mCancelerManager;
        private DownloadRequest mRequest;

        public AsyncCallback(DownloadListener callback) {
            this.mCallback = callback;
        }

        public void setQueue(BlockingQueue<Work<? extends DownloadRequest>> queue) {
            mQueue = queue;
        }

        public void setWork(Work<? extends DownloadRequest> work) {
            mWork = work;
        }

        public void setCancelerManager(CancelerManager cancelerManager) {
            mCancelerManager = cancelerManager;
        }

        public void setRequest(DownloadRequest request) {
            mRequest = request;
        }

        @Override
        public void onDownloadError(final int what, final Exception exception) {
            removeRequest();
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onDownloadError(what, exception);
                }
            });
        }

        @Override
        public void onStart(final int what, final boolean isResume, final long rangeSize,
                            final Headers headers, final long allCount) {
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onStart(what, isResume, rangeSize, headers, allCount);
                }
            });
        }

        @Override
        public void onProgress(final int what, final int progress, final long fileCount, final long speed) {
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onProgress(what, progress, fileCount, speed);
                }
            });
        }

        @Override
        public void onFinish(final int what, final String filePath) {
            removeRequest();
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onFinish(what, filePath);
                }
            });
        }

        @Override
        public void onCancel(final int what) {
            removeRequest();
            HandlerDelivery.getInstance().post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onCancel(what);
                }
            });
        }

        private void removeRequest() {
            mCancelerManager.removeCancel(mRequest);
            if (mQueue.contains(mWork)) {
                mQueue.remove(mWork);
            }
        }
    }

}


Question: import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;
import com.yanzhenjie.nohttp.download.DownloadQueue;
import com.yanzhenjie.nohttp.download.DownloadRequest;
import com.yanzhenjie.nohttp.rest.ByteArrayRequest;
import com.yanzhenjie.nohttp.rest.ImageRequest;
import com.yanzhenjie.nohttp.rest.JsonArrayRequest;
import com.yanzhenjie.nohttp.rest.JsonObjectRequest;
import com.yanzhenjie.nohttp.rest.Request;
import com.yanzhenjie.nohttp.rest.RequestQueue;
import com.yanzhenjie.nohttp.rest.Response;
import com.yanzhenjie.nohttp.rest.StringRequest;
import com.yanzhenjie.nohttp.rest.SyncRequestExecutor;
/*
 * Copyright 2015 Yan Zhenjie
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.yanzhenjie.nohttp;




/**
 * <p>
 * NoHttp.
 * </p>
 * Created in Jul 28, 2015 7:32:22 PM.
 *
 * @author Yan Zhenjie.
 */
public class NoHttp {

    private static InitializationConfig sInitializeConfig;

    private NoHttp() {
    }

    /**
     * Initialize NoHttp, should invoke on {@link android.app.Application#onCreate()}.
     *
     * @param context {@link Context}.
     */
    public static void initialize(Context context) {
        initialize(InitializationConfig.newBuilder(context).build());
    }

    /**
     * Initialize NoHttp, should invoke on {@link android.app.Application#onCreate()}.
     */
    public static void initialize(InitializationConfig initializeConfig) {
        sInitializeConfig = initializeConfig;
    }

    /**
     * Test initialized.
     */
    private static void testInitialize() {
        if (sInitializeConfig == null)
            throw new ExceptionInInitializerError("Please invoke NoHttp.initialize(Application) on Application#onCreate()");
    }

    /**
     * Gets context of app.
     */
    public static Context getContext() {
        testInitialize();
        return sInitializeConfig.getContext();
    }

    /**
     * Get InitializationConfig.
     */
    public static InitializationConfig getInitializeConfig() {
        testInitialize();
        return sInitializeConfig;
    }

    /**
     * Create a queue of handle, the default thread pool size is 3.
     *
     * @return returns the handle queue, the queue is used to control the entry of the handle.
     * @see #newRequestQueue(int)
     */
    public static RequestQueue newRequestQueue() {
        return newRequestQueue(3);
    }

    /**
     * Create a queue of handle.
     *
     * @param threadPoolSize handle the number of concurrent.
     * @return returns the handle queue, the queue is used to control the entry of the handle.
     * @see #newRequestQueue()
     */
    public static RequestQueue newRequestQueue(int threadPoolSize) {
        RequestQueue requestQueue = new RequestQueue(threadPoolSize);
        requestQueue.start();
        return requestQueue;
    }

    /**
     * Create a String type handle, the handle method is {@link RequestMethod#GET}.
     *
     * @param url such as: {@code http://www.nohttp.net}.
     * @return {@code Request<String>}.
     * @see #createStringRequest(String, RequestMethod)
     */
    public static Request<String> createStringRequest(String url) {
        return new StringRequest(url);
    }

    /**
     * Create a String type handle, custom handle method, method from {@link RequestMethod}.
     *
     * @param url           such as: {@code http://www.nohttp.net}.
     * @param requestMethod {@link RequestMethod}.
     * @return {@code Request<String>}.
     * @see #createStringRequest(String)
     */
    public static Request<String> createStringRequest(String url, RequestMethod requestMethod) {
        return new StringRequest(url, requestMethod);
    }

    /**
     * Create a JSONObject type handle, the handle method is {@link RequestMethod#GET}.
     *
     * @param url such as: {@code http://www.nohttp.net}.
     * @return {@code Request<JSONObject>}.
     * @see #createJsonObjectRequest(String, RequestMethod)
     */
    public static Request<JSONObject> createJsonObjectRequest(String url) {
        return new JsonObjectRequest(url);
    }

    /**
     * Create a JSONObject type handle, custom handle method, method from {@link RequestMethod}.
     *
     * @param url           such as: {@code http://www.nohttp.net}.
     * @param requestMethod {@link RequestMethod}.
     * @return {@code Request<JSONObject>}.
     * @see #createJsonObjectRequest(String)
     */
    public static Request<JSONObject> createJsonObjectRequest(String url, RequestMethod requestMethod) {
        return new JsonObjectRequest(url, requestMethod);
    }

    /**
     * Create a JSONArray type handle, the handle method is {@link RequestMethod#GET}.
     *
     * @param url such as: {@code http://www.nohttp.net}.
     * @return {@code Request<JSONArray>}.
     * @see #createJsonArrayRequest(String, RequestMethod)
     */
    public static Request<JSONArray> createJsonArrayRequest(String url) {
        return new JsonArrayRequest(url);
    }

    /**
     * Create a JSONArray type handle, custom handle method, method from {@link RequestMethod}.
     *
     * @param url           such as: {@code http://www.nohttp.net}.
     * @param requestMethod {@link RequestMethod}.
     * @return {@code Request<JSONArray>}.
     * @see #createJsonArrayRequest(String)
     */
    public static Request<JSONArray> createJsonArrayRequest(String url, RequestMethod requestMethod) {
        return new JsonArrayRequest(url, requestMethod);
    }

    /**
     * Create a Image type handle, the handle method is {@link RequestMethod#GET}.
     *
     * @param url such as: {@code http://www.nohttp.net}.
     * @return {@code Request<Bitmap>}.
     * @see #createImageRequest(String, RequestMethod)
     * @see #createImageRequest(String, RequestMethod, int, int, Bitmap.Config, ImageView.ScaleType)
     */
    public static Request<Bitmap> createImageRequest(String url) {
        return createImageRequest(url, RequestMethod.GET);
    }

    /**
     * Create a Image type handle.
     *
     * @param url           such as: {@code http://www.nohttp.net}.
     * @param requestMethod {@link RequestMethod}.
     * @return {@code Request<Bitmap>}.
     * @see #createImageRequest(String)
     * @see #createImageRequest(String, RequestMethod, int, int, Bitmap.Config, ImageView.ScaleType)
     */
    public static Request<Bitmap> createImageRequest(String url, RequestMethod requestMethod) {
        return createImageRequest(url, requestMethod, 1000, 1000, Bitmap.Config.ARGB_8888, ImageView.ScaleType.CENTER_INSIDE);
    }

    /**
     * Create a Image type handle.
     *
     * @param url           such as: {@code http://www.nohttp.net}.
     * @param requestMethod {@link RequestMethod}.
     * @param maxWidth      width.
     * @param maxHeight     height.
     * @param config        config.
     * @param scaleType     scaleType.
     * @return {@code Request<Bitmap>}.
     * @see #createImageRequest(String)
     * @see #createImageRequest(String, RequestMethod)
     */
    public static Request<Bitmap> createImageRequest(String url, RequestMethod requestMethod,
                                                     int maxWidth, int maxHeight,
                                                     Bitmap.Config config, ImageView.ScaleType scaleType) {
        return new ImageRequest(url, requestMethod, maxWidth, maxHeight, config, scaleType);
    }

    /**
     * Create a byte array handle, the handle method is {@link RequestMethod#GET}.
     *
     * @param url url.
     * @return {@code Request<byte[]>}.
     * @see #createByteArrayRequest(String, RequestMethod)
     */
    public static Request<byte[]> createByteArrayRequest(String url) {
        return new ByteArrayRequest(url);
    }

    /**
     * Create a byte array handle.
     *
     * @param url    url.
     * @param method {@link RequestMethod}.
     * @return {@code Request<byte[]>}.
     * @see #createByteArrayRequest(String)
     */
    public static Request<byte[]> createByteArrayRequest(String url, RequestMethod method) {
        return new ByteArrayRequest(url, method);
    }

    /**
     * Initiate a synchronization handle.
     *
     * @param request handle object.
     * @param <T>     {@link T}.
     * @return {@link Response}.
     */
    public static <T> Response<T> startRequestSync(Request<T> request) {
        return SyncRequestExecutor.INSTANCE.execute(request);
    }

    /**
     * Create a new download queue, the default thread pool size is 3.
     *
     * @return {@link DownloadQueue}.
     * @see #newDownloadQueue(int)
     */
Answer:     public static DownloadQueue newDownloadQueue() {