3
\$\begingroup\$

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
            }
        }
    };
\$\endgroup\$

4 Answers 4

3
\$\begingroup\$

Your idea seems quite feasible, I just had a brief look through and these would be my suggestions:

  1. TaskResult class

    • "code" and "message" members should probably be encapsulated via getter/setter with proper namings.
  2. 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.

\$\endgroup\$
1
  • \$\begingroup\$ Yeah, your points are very noteworthy and I will add them to my original code. \$\endgroup\$ Feb 26, 2014 at 11:22
3
\$\begingroup\$

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..

\$\endgroup\$
1
\$\begingroup\$

It's simple and elegant and useful for many cases but I'd do something else

  1. I would enhance HttpRequest with Multipart (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)
  2. I would enhance HttpResponse instead TaskResult and there, I would also use Multipart
\$\endgroup\$
0
1
\$\begingroup\$

Just one thing I'd like to mention here.

  1. In your AsyncTask you are not doing anything in onPreExecute() so I would remove it.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.