I am working on Android applications for last 2 years and about 80% applications I have developed involve web-services consumption followed by some sort of XML or JSON parsing. Initially, when I had to call a web service, I had to create a separate AsyncTask
class and then parsing was also the part of that AsyncTask class. The HTTP request sending and other stuff was being handled in my ConnectionManager
class. Then I realized there should be some general and single structure which can handle such things like Async
call, HttpGet
and HttpPost
and parsing stuff. So I created this simple structure.
Now my question is, what changes and improvements I can add to make it work better and handle such different use cases?
TaskResult.class
public class TaskResult {
public static int CODE_ERROR = 0;
public static int CODE_SUCCESS = 1;
public int code = CODE_ERROR;
public String message = null;
private Object data = null;
public Object getResultData() {
return data;
}
public void setResultData(Object data) {
this.data = data;
}
}
BaseParser.class
public interface BaseParser {
public TaskResult parse(InputStream in);
}
ConnectionManager.class
public class ConnectionManager {
private ArrayList <NameValuePair> params;
private ArrayList <NameValuePair> headers;
private String url;
public static int GET_REQUEST = 0;
public static int POST_REQUEST = 1;
private int mRequestType = POST_REQUEST;
public ConnectionManager() {
params = new ArrayList<NameValuePair>();
headers = new ArrayList<NameValuePair>();
}
public void addParam(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public void addHeader(String name, String value) {
headers.add(new BasicNameValuePair(name, value));
}
public void setRequestType(int type) {
mRequestType = type;
}
public void setUrl(String url) {
this.url = url;
}
public InputStream getHttpInputStream() throws ClientProtocolException, Exception {
if(url == null) {
throw new NullPointerException();
}
System.setProperty("http.keepAlive", "false");
if(mRequestType == POST_REQUEST) {
HttpPost request = new HttpPost(url);
request.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
for(int i = 0; i < headers.size(); i++) {
StringEntity entity = new StringEntity(headers.get(i).getValue(), "UTF-8");
request.setEntity(entity);
}
if(!params.isEmpty()){
HttpEntity httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
request.setEntity(httpEntity);
}
DefaultHttpClient mClient = new DefaultHttpClient();
HttpResponse httpResponse;
httpResponse = mClient.execute(request);
HttpEntity mEntity = httpResponse.getEntity();
if (mEntity != null) {
return mEntity.getContent();
}
}
else if(mRequestType == GET_REQUEST) {
String queryString = "";
for(int i = 0; i < params.size(); i++) {
if(i == 0) {
queryString = queryString + params.get(i).getName( ) + "=" + params.get(i).getValue();
}
else {
queryString = queryString + "&" + params.get(i).getName( ) + "=" + params.get(i).getValue();
}
}
DefaultHttpClient mClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url + queryString);
HttpResponse httpResponse;
httpResponse = mClient.execute(httpGet);
HttpEntity mEntity = httpResponse.getEntity();
if (mEntity != null) {
return mEntity.getContent();
}
}
return null;
}
}
BaseAsyncTask.class
public class BaseAsyncTask extends AsyncTask<Void, Integer, TaskResult>{
ConnectionManager mConnectionManager = null;
OnTaskCompleteListener mListener;
BaseParser mParser;
public BaseAsyncTask.class() {
mConnectionManager = new ConnectionManager();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected TaskResult doInBackground(Void... params) {
String message = "";
try {
InputStream in = mConnectionManager.getTestInputStream();
return mParser.parse(in);
} catch (ClientProtocolException e) {
e.printStackTrace();
message = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
message = e.getMessage();
} catch(Exception e) {
e.printStackTrace();
message = e.getMessage();
}
TaskResult rs = new TaskResult();
rs.message = "Internal error. Please try later." + message;
return rs;
}
@Override
protected void onPostExecute(TaskResult result) {
super.onPostExecute(result);
mListener.onComplete(result);
}
public void setRequestType(int type) {
mConnectionManager.setRequestType(type);
}
public void setUrl(String url) {
mConnectionManager.setUrl(url);
}
public void addParam(String name, String value) {
mConnectionManager.addParam(name, value);
}
public void addHeader(String name, String value) {
mConnectionManager.addHeader(name, value);
}
public void setCallbackListener(OnTaskCompleteListener listener) {
this.mListener = listener;
}
public void setParser(BaseParser parser) {
this.mParser = parser;
}
public interface OnTaskCompleteListener {
public void onComplete(TaskResult rs);
}
}
and this is how I call a web-service:
BaseAsyncTask mAsyncTask = new BaseAsyncTask();
mAsyncTask.setUrl(WEB_URL);
mAsyncTask.addParam("id", "some_id");
mAsyncTask.setRequestType(ConnectionManager.GET_REQUEST);
mAsyncTask.setCallbackListener(callbackListener);
mAsyncTask.setParser(new MyListingParser());
mAsyncTask.execute();
public class MyListingParser implements BaseParser {
@Override
public TaskResult parse(InputStream in) {
TaskResult result = new TaskResult();
// convert inputstream to string and then parse
ArrayList<MyClass> data = parseString(in);
result.setResultData(data);
result.code = TaskResult.CODE_SUCCESS;
return result;
}
}
private OnTaskCompleteListener callbackListener = new OnTaskCompleteListener() {
@Override
public void onComplete(TaskResult rs) {
if(rs.code == TaskResult.CODE_ERROR) {
// handle error
}
else if(rs.code == TaskResult.CODE_SUCCESS) {
// handle success case like getting data from TaskResult and populating some listview or other stuff
}
}
};
4 Answers 4
Your idea seems quite feasible, I just had a brief look through and these would be my suggestions:
TaskResult class
- "code" and "message" members should probably be encapsulated via getter/setter with proper namings.
ConnectionManager class
- Depending on your scenario maybe you should consider calling "shutdown" on your mClient member.
- When creating your queryString you should use String.format() instead of manually concatenating strings.
- The getHttpInputStream() method could suffer a bit of refactoring, you have common code and behaviour in both if/else branches.
Other then that, imo the code looks okey.
-
\$\begingroup\$ Yeah, your points are very noteworthy and I will add them to my original code. \$\endgroup\$Khawar Raza– Khawar Raza2014年02月26日 11:22:08 +00:00Commented Feb 26, 2014 at 11:22
I use volley library to do these work. Volley is a library developed by Google, it is tried and tested. It has other features network response caching, network image caching, request cancelation etc..
It's simple and elegant and useful for many cases but I'd do something else
- I would enhance
HttpRequest
withMultipart
(I know, it's not what you wanted but it's very useful for Http Connections, if you want to upload/download something,Multipart is a MUST) - I would enhance
HttpResponse
insteadTaskResult
and there, I would also use Multipart
Just one thing I'd like to mention here.
- In your AsyncTask you are not doing anything in
onPreExecute()
so I would remove it.
Explore related questions
See similar questions with these tags.