Created
May 29, 2013 16:04
-
-
Save sarahsnow1/5671467 to your computer and use it in GitHub Desktop.
An API client for the Volley networking library modelled after AFNetworking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.eatify.Eatify.api; | |
public class EatifyApiClient extends VolleyApiClient { | |
private static volatile EatifyApiClient instance; | |
public static EatifyApiClient shared() { | |
if (instance == null) { | |
synchronized (EatifyApiClient.class) { | |
if (instance == null) { | |
instance = new EatifyApiClient(); | |
} | |
} | |
} | |
return instance; | |
} | |
public EatifyApiClient() { | |
super(); | |
mBaseUrl = "http://eatify-backend.herokuapp.com"; | |
mDefaultHeaders.put("Accept", "application/json"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void search(String query) { | |
Map<String, String> params = new HashMap<String, String>(); | |
params.put("count", "10"); | |
params.put("name", query); | |
EatifyApiClient.shared().get("/restaurants/autocomplete", params, new Response.Listener<StringResponse>() { | |
@Override | |
public void onResponse(StringResponse response) { | |
textView.setText(response.getResponse()); | |
} | |
}, new Response.ErrorListener() { | |
@Override | |
public void onErrorResponse(VolleyError error) { | |
textView.setText("Error: "+error.getLocalizedMessage()); | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.android.volley.NetworkResponse; | |
public class StringResponse extends NetworkResponse { | |
protected String response; | |
public StringResponse(NetworkResponse networkResponse) { | |
super(networkResponse.statusCode, networkResponse.data, networkResponse.headers, networkResponse.notModified); | |
this.response = new String(networkResponse.data); | |
} | |
public String getResponse() { | |
return response; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import com.android.volley.*; | |
import com.android.volley.toolbox.Volley; | |
import java.io.UnsupportedEncodingException; | |
import java.net.URLEncoder; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
public class VolleyApiClient { | |
protected RequestQueue mRequestQueue; | |
// Subclass should configure | |
protected String mBaseUrl = null; | |
protected Map<String, String> mDefaultHeaders = new HashMap<String, String>(); | |
private static volatile VolleyApiClient instance; | |
public static VolleyApiClient shared() { | |
if (instance == null) { | |
synchronized (VolleyApiClient.class) { | |
if (instance == null) { | |
instance = new VolleyApiClient(); | |
} | |
} | |
} | |
return instance; | |
} | |
public void start(Context context) { | |
mRequestQueue = Volley.newRequestQueue(context); | |
} | |
public RequestQueue getRequestQueue() { | |
if (mRequestQueue != null) { | |
return mRequestQueue; | |
} else { | |
throw new IllegalStateException("RequestQueue not initialized"); | |
} | |
} | |
protected String fullyQualifiedUrlForPath(String path) { | |
if (mBaseUrl != null) { | |
return mBaseUrl+path; | |
} | |
else { | |
throw new IllegalStateException("BaseUrl not initialized"); | |
} | |
} | |
private String flattenParams(Map<String, String> inParameters) { | |
StringBuilder params = null; | |
Iterator it = inParameters.entrySet().iterator(); | |
while (it.hasNext()) { | |
if (params == null) { | |
params = new StringBuilder(); | |
params.append("?"); | |
} | |
else { | |
params.append("&"); | |
} | |
Map.Entry pairs = (Map.Entry)it.next(); | |
String key = null; | |
String val = null; | |
try { | |
key = URLEncoder.encode((String) pairs.getKey(), "UTF-8"); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
} | |
try { | |
val = URLEncoder.encode((String) pairs.getValue(), "UTF-8"); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
} | |
params.append(key+"="+val); | |
} | |
return params.toString(); | |
} | |
public Request request(int method, String path, Map<String, String> inParameters, Map<String, String> inHeaders, Response.Listener onSuccess, Response.ErrorListener onFailure) { | |
final Response.Listener listener = onSuccess; | |
final Map<String, String> params = inParameters; | |
final Map<String, String> headers = inHeaders; | |
if (method == Request.Method.GET && params != null) { | |
path = path+flattenParams(params); | |
} | |
Request request = new Request(method, fullyQualifiedUrlForPath(path), onFailure) { | |
@Override | |
protected Response parseNetworkResponse(NetworkResponse networkResponse) { | |
StringResponse stringResponse = new StringResponse(networkResponse); | |
return Response.success(stringResponse, getCacheEntry()); | |
} | |
@Override | |
protected void deliverResponse(Object o) { | |
listener.onResponse(o); | |
} | |
@Override | |
protected Map<String, String> getParams() throws AuthFailureError { | |
return params; | |
} | |
@Override | |
public Map<String, String> getHeaders() throws AuthFailureError { | |
Map<String, String> allHeaders = new HashMap<String, String>(); | |
allHeaders.putAll(super.getHeaders()); | |
if (mDefaultHeaders != null) { | |
allHeaders.putAll(mDefaultHeaders); | |
} | |
if (headers!= null) { | |
allHeaders.putAll(headers); | |
} | |
return allHeaders; | |
} | |
}; | |
mRequestQueue.add(request); | |
return request; | |
} | |
public Request get(String path, Map<String, String> parameters, Response.Listener onSuccess, Response.ErrorListener onFailure) { | |
return request(Request.Method.GET, path, parameters, null, onSuccess, onFailure); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've used a similar pattern in a few apps I've worked on with Volley, but instead of making an abstract API pattern, I think it makes for nicer code to actually make something like a Java version of your REST API.
Something like this:
This is a simplified case, you might need to have your own Request subclass to do the header stuff. I'm thinking we should probably add an API in Volley to add your own headers to any baseline request so you don't have to do that, but for the time being...
Also, more of a personal style thing but I'd drop all the synchronized stuff and instead assert that you're on the main thread. Don't lock unless you really have to!