Skip to content

Instantly share code, notes, and snippets.

@SarthakM9
Last active October 5, 2016 18:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SarthakM9/8ba9d34afcbd6bbc38cb8f5480c19f3f to your computer and use it in GitHub Desktop.
Save SarthakM9/8ba9d34afcbd6bbc38cb8f5480c19f3f to your computer and use it in GitHub Desktop.
A wrapper class around Volley Library, to make api calling a breeze. DO READ THE COMMENTS CAREFULLY!
/**
* The MIT License (MIT)
*
* Copyright (c) 2016 Sarthak Mittal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* Custom Wrapper around Volley to send web requests along with headers if any. It provides the
* option to parse the data into model object using gson or return the raw response as a String.
* It also provides a single interface for response success and failure. You need to assign URLs
* a requestId to uniquely identify them and invoke/parse multiple web calls simultaneously.
*/
public class CustomHttpRequest<T> extends Request<T>
{
private String mRequestBody;
private Map<String, String> mRequestHeader;
private Class<T> mModelClass;
private final Gson mGson = new Gson();
private static final String PROTOCOL_CHARSET = "utf-8";
private static final String PROTOCOL_CONTENT_TYPE_JSON = String.format("application/json; " +
"charset=%s", PROTOCOL_CHARSET);
private static final String PROTOCOL_CONTENT_TYPE_URLENCODED = String.format
("application/x-www-form-urlencoded; charset=%s", PROTOCOL_CHARSET);
private InternalListener mInternalListener;
private int mRequestId;
private CustomHttpRequest()
{
super(Method.GET, null, null);
}
/**
* @param method int specifying service type. ex: Request.Method.GET
* @param url URL to hit.
* @param requestID manually set id to keep track of the url being hit, it is used to keep
* track of response object and response error.
* @param header header to send, if any.
* @param body parameters to send(generally JSONObject) as a String, if any.
* @param timeOut timeOut in milliseconds.
* @param modelClass GSON model class object to populate data, pass null if raw String
* response is required.
* @param listener Custom response listener class object, return type of response is an
* Object which can further be cast to desired type using requestId.
*/
public CustomHttpRequest(int method, @NonNull String url, int requestID, @Nullable
Map<String, String> header, @Nullable String body, int timeOut, @Nullable Class<T>
modelClass, HttpResponseListener listener)
{
super(method, url, listener == null ? null : new InternalListener(listener, requestID));
mInternalListener = (InternalListener) this.getErrorListener();
mRequestId = requestID;
mRequestBody = body;
mRequestHeader = header;
mModelClass = modelClass;
setRetryPolicy(new DefaultRetryPolicy(timeOut, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
/**
* @param method int specifying service type. ex: Request.Method.GET
* @param url URL to hit.
* @param requestID manually set id to keep track of the url being hit, it is used to keep
* track of response object and response error.
* @param header header to send, if any.
* @param body parameters to send(generally JSONObject) as a String, if any.
* @param modelClass GSON model class object to populate data, pass null if raw String
* response is required
* @param listener Custom response listener class object, return type of response is an
* Object which can futher be cast to desired type using urlID.
*/
public CustomHttpRequest(int method, @NonNull String url, int requestID, @Nullable
Map<String, String> header, @Nullable String body, @Nullable Class<T> modelClass,
HttpResponseListener listener)
{
this(method, url, requestID, header, body, 12000, modelClass, listener); /*default time
is 12 secs*/
}
/**
* Executes on a worker thread, parsing is done here.
*/
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response)
{
try
{
// The response is returned either as the type passed in modelClass argument or as a
// String if null is passed, note that the response is always up casted to an Object,
// You need to downcast it manually, on the basis of requestId parameter.
String responseString = new String(response.data, HttpHeaderParser.parseCharset
(response.headers, PROTOCOL_CHARSET));
if (mModelClass == null)
{
return Response.success((T) responseString, HttpHeaderParser.parseCacheHeaders
(response));
} else
{
return Response.success(mGson.fromJson(responseString, mModelClass),
HttpHeaderParser.parseCacheHeaders(response));
}
} catch (UnsupportedEncodingException e)
{
return Response.error(new ParseError(e));
} catch (Exception e)
{
return Response.error(new ParseError(e));
}
}
/**
* Executes on the main thread;
*/
@Override
protected void deliverResponse(T response)
{
if (mInternalListener != null)
{
mInternalListener.onResponse(response);
}
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError
{
return mRequestHeader != null ? mRequestHeader : super.getHeaders();
}
@Override
public String getBodyContentType()
{
// For setting another content type, apply switch statement on mRequestId
switch (mRequestId)
{
// To change the content type for a particular endpoint, just add relevant case statement.
// case ID_AUTH_TOKEN:
// return PROTOCOL_CONTENT_TYPE_URLENCODED;
default:
return PROTOCOL_CONTENT_TYPE_JSON;
}
}
@Override
public byte[] getBody()
{
try
{
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee)
{
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
mRequestBody, PROTOCOL_CHARSET);
return null;
}
}
// Remove this method to get default volleyError object.
@Override
protected VolleyError parseNetworkError(VolleyError volleyError)
{
if (volleyError.networkResponse != null && volleyError.networkResponse.data != null)
{
volleyError = new VolleyError(new String(volleyError.networkResponse.data));
}
return volleyError;
}
}
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.android.volley.Request;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.Volley;
// Add import statements for your CustomHttpRequest and HttpResponseListener.
public class ExampleActivity extends AppCompatActivity implements HttpResponseListener
{
private static final int ID_SERVICE_EXAMPLE = 1;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
invokeGetRequest();
}
});
}
private void invokeGetRequest()
{
String url = "SOME_URL";
CustomHttpRequest<YourGsonModelClass> request = new CustomHttpRequest<>(Request.Method
.GET, url, ID_SERVICE_EXAMPLE, null, null, YourGsonModelClass.class, this);
// Recommended to create a singleton of Volley RequestQueue in Application class.
Volley.newRequestQueue(this).add(request);
}
@Override
public void onResponseSuccess(Object response, int requestID)
{
switch (requestID)
{
case ID_SERVICE_EXAMPLE:
YourGsonModelClass model = (YourGsonModelClass) response;
// You get a completely parsed model.
break;
}
}
@Override
public void onResponseError(VolleyError error, int requestID)
{
switch (requestID)
{
case ID_SERVICE_EXAMPLE:
// Log error for this particular service.
break;
}
}
}
/**
* The MIT License (MIT)
*
* Copyright (c) 2016 Sarthak Mittal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import com.android.volley.Response;
import com.android.volley.VolleyError;
/**
* Interface which is implemented by other classes to get service response, it sends requestID as
* parameter along with the original volley response parameter.
* PUT THIS INSIDE THE SAME PACKAGE AS OF CustomHttpRequest.java
*/
public interface HttpResponseListener
{
void onResponseSuccess(Object response, int requestID);
void onResponseError(VolleyError error, int requestID);
}
/*This class is used internally in CustomHttpRequest class*/
class InternalListener implements Response.ErrorListener, Response.Listener<Object>
{
private final HttpResponseListener mListener;
private final int mRequestID;
public InternalListener(HttpResponseListener listener, int requestID)
{
mListener = listener;
mRequestID = requestID;
}
@Override
public void onErrorResponse(VolleyError error)
{
mListener.onResponseError(error, mRequestID);
}
@Override
public void onResponse(Object response)
{
mListener.onResponseSuccess(response, mRequestID);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment