如何将HttpUrlConnection的逻辑拆分为多个方法?

时间:2015-12-22 03:48:39

标签: java android android-asynctask httpurlconnection

我有多个活动,每个活动都会从不同的网址和不同的HTTP方法获取不同的数据,例如POSTGETPUTDELETE等。 有些请求有标题数据,有些请求有Body,有些可能有两个。 我正在使用带有多个构造函数的单个AsyncTask类来传递活动中的数据,以便我可以将它们添加到HttpUrlConnection实例。

我尝试了本教程:http://cyriltata.blogspot.in/2013/10/android-re-using-asynctask-class-across.html

但上述教程使用HttpClientNameValuePair。我将NameValuePair替换为Pair。但我发现很难使用HttpUrlConnection实现相同的逻辑,因为我需要在我的请求中添加多个POST数据和标题。

但返回的String是空的。如何正确实施此方案?

完整代码:

public class APIAccessTask extends AsyncTask<String,Void,String> {
URL requestUrl;
Context context;
HttpURLConnection urlConnection;
List<Pair<String,String>> postData, headerData;
String method;
int responseCode = HttpURLConnection.HTTP_NOT_FOUND;


APIAccessTask(Context context, String requestUrl, String method){
    this.context = context;
    this.method = method;
    try {
        this.requestUrl = new URL(requestUrl);
    }
    catch(Exception ex){
        ex.printStackTrace();
    }
 }


APIAccessTask(Context context, String requestUrl, String method,    List<Pair<String,String>> postData,){
    this(context, requestUrl, method);
    this.postData = postData;
}

APIAccessTask(Context context, String requestUrl, String method, List<Pair<String,String>> postData,
              List<Pair<String,String>> headerData){
    this(context, requestUrl,method,postData);
    this.headerData = headerData;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected String doInBackground(String... params) {

    setupConnection();

    if(method.equals("POST"))
    {
        return httpPost();
    }

    if(method.equals("GET"))
    {
        return httpGet();
    }

    if(method.equals("PUT"))
    {
        return httpPut();
    }

    if(method.equals("DELETE"))
    {
        return httpDelete();
    }
    if(method.equals("PATCH"))
    {
        return httpPatch();
    }

    return null;
}

@Override
protected void onPostExecute(String result) {
    Toast.makeText(context,result,Toast.LENGTH_LONG).show();
    super.onPostExecute(result);
}

void setupConnection(){
    try {
        urlConnection = (HttpURLConnection) requestUrl.openConnection();
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setChunkedStreamingMode(0);
        if(headerData != null){
            for (Pair pair: headerData)
            {
                urlConnection.setRequestProperty(pair.first.toString(), Base64.encodeToString(pair.second.toString().getBytes(),Base64.DEFAULT));
            }
        }
    }
    catch(Exception ex) {
        ex.printStackTrace();
    }

}

private String httpPost(){
    try{
        urlConnection.setRequestMethod("POST");
    }
    catch (Exception ex){
        ex.printStackTrace();

    return stringifyResponse();
}

String httpGet(){

    try{
        urlConnection.setRequestMethod("GET");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();
}

String httpPut(){

    try{
        urlConnection.setRequestMethod("PUT");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();
}

String httpDelete(){
    try{
        urlConnection.setRequestMethod("DELETE");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();

}

String httpPatch(){
    try{
        urlConnection.setRequestMethod("PATCH");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();

}

String stringifyResponse() {

    StringBuilder sb = new StringBuilder();
    try {
        OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
        writer.write(getQuery(postData));
        writer.flush();
        writer.close();
        out.close();

        urlConnection.connect();
        responseCode = urlConnection.getResponseCode();
        if (responseCode == 200) {
            InputStream in = new BufferedInputStream(urlConnection.getInputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line = null;

            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return sb.toString();
}


private String getQuery(List<Pair<String,String>> params) throws UnsupportedEncodingException{
    Uri.Builder builder = null;
    for (Pair pair : params)
    {
         builder = new Uri.Builder()
                .appendQueryParameter(pair.first.toString(), pair.second.toString());
                }
    return builder.build().getEncodedQuery();
}
}

2 个答案:

答案 0 :(得分:1)

IMO,您可以参考我的以下示例代码:

   /**         
     * HTTP request using HttpURLConnection
     *
     * @param method
     * @param address
     * @param header
     * @param mimeType
     * @param requestBody
     * @return
     * @throws Exception
     */
    public static URLConnection makeURLConnection(String method, String address, String header, String mimeType, String requestBody) throws Exception {
        URL url = new URL(address);

        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(!method.equals(HTTP_METHOD_GET));
        urlConnection.setRequestMethod(method);

        if (isValid(header)) {   // let's assume only one header here             
            urlConnection.setRequestProperty(KEYWORD_HEADER_1, header);
        }

        if (isValid(requestBody) && isValid(mimeType) && !method.equals(HTTP_METHOD_GET)) {
            urlConnection.setRequestProperty(KEYWORD_CONTENT_TYPE, mimeType);
            OutputStream outputStream = new BufferedOutputStream(urlConnection.getOutputStream());
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8");
            writer.write(requestBody);
            writer.flush();
            writer.close();
            outputStream.close();
        }

        urlConnection.connect();

        return urlConnection;
    }

requestBody是使用以下方法制作的:

    public static String buildRequestBody(Object content) {
        String output = null;
        if ((content instanceof String) ||
                (content instanceof JSONObject) ||
                (content instanceof JSONArray)) {
            output = content.toString();
        } else if (content instanceof Map) {
            Uri.Builder builder = new Uri.Builder();
            HashMap hashMap = (HashMap) content;
            if (isValid(hashMap)) {
                Iterator entries = hashMap.entrySet().iterator();
                while (entries.hasNext()) {
                    Map.Entry entry = (Map.Entry) entries.next();
                    builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
                    entries.remove(); // avoids a ConcurrentModificationException
                }
                output = builder.build().getEncodedQuery();
            }
        } else if (content instanceof byte[]) {
            try {
                output = new String((byte[]) content, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        return output;
    }
}

然后,在AsyncTask类中,您可以调用:

       String url = "http://.......";
       HttpURLConnection urlConnection;
       Map<String, String> stringMap = new HashMap<>();           
       stringMap.put(KEYWORD_USERNAME, "bnk");
       stringMap.put(KEYWORD_PASSWORD, "bnk123");
       String requestBody = buildRequestBody(stringMap);
       try {
           urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_FORM_URLENCODED, requestBody);               
           if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
               // do something...
           } else {
               // do something...
           }
           ...
       } catch (Exception e) {
           e.printStackTrace();
       }

       String url = "http://.......";
       HttpURLConnection urlConnection;
       JSONObject jsonBody;                      
       String requestBody;
       try {
           jsonBody = new JSONObject();
           jsonBody.put("Title", "Android Demo");
           jsonBody.put("Author", "BNK");
           requestBody = Utils.buildRequestBody(jsonBody);
           urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_JSON, requestBody);               
           if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
               // do something...
           } else {
               // do something...
           }
           ...
       } catch (Exception e) {
           e.printStackTrace();
       }

答案 1 :(得分:1)

让我们在这里应用一些oops概念 有一个类HttpCommunication将纯粹负责发送请求并从服务器获取响应。示例代码如下

package com.example.sample;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

public class HttpCommunication {
    public String makeHttpRequest( String url, HttpMethods method, ArrayList< NameValuePair > requestParams, ArrayList< NameValuePair > postData ) throws Exception {

        InputStream inputStream = null;
        String response = "";
        HttpParams httpParameters = new BasicHttpParams( );

        /**
         * Set the timeout in milliseconds until a connection is established. The default value is
         * zero, that means the timeout is not used.
         */
        int timeoutConnection = 15000;
        HttpConnectionParams.setConnectionTimeout( httpParameters, timeoutConnection );

        /**
         * Set the default socket timeout (SO_TIMEOUT) in milliseconds which is the timeout for
         * waiting for data.
         */
        int timeoutSocket = 15000;
        HttpConnectionParams.setSoTimeout( httpParameters, timeoutSocket );

        DefaultHttpClient httpClient = new DefaultHttpClient( httpParameters );

        /**
         * Check for request method
         */
        if ( method == HttpMethods.POST ) {
            HttpPost httpPost = new HttpPost( url );

            if ( requestParams != null && requestParams.size( ) > 0 ) {
                httpPost.setEntity( new UrlEncodedFormEntity( requestParams ) );
            }

            HttpResponse httpResponse = httpClient.execute( httpPost );
            HttpEntity httpEntity = httpResponse.getEntity( );
            inputStream = httpEntity.getContent( );

        } else if ( method == HttpMethods.GET ) {
            if ( requestParams != null && requestParams.size( ) > 0 ) {
                String paramString = URLEncodedUtils.format( requestParams, "utf-8" );
                url += "?" + paramString;
            }

            HttpGet httpGet = new HttpGet( url );

            HttpResponse httpResponse = httpClient.execute( httpGet );
            HttpEntity httpEntity = httpResponse.getEntity( );
            inputStream = httpEntity.getContent( );
        }

        BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream, "UTF-8" ) );
        StringBuilder sb = new StringBuilder( );
        String line = null;
        while ( ( line = reader.readLine( ) ) != null ) {
            sb.append( line + "\n" );
        }
        inputStream.close( );
        response = sb.toString( );

        return response;
    }
}

有一个抽象基类,它将作为应用程序中所有底层Web服务的模板。 该类将使用上面的HttpCommunication类来发送请求。 请求将从AsyncTask发送,因此它是完全异步的。 该类将提供派生类必须覆盖的抽象方法,并为其提供定义; 1. getUrl() - 格式正确的请求网址 2. getHttpMethod() - 来自GET,POST,PUT,DELETE,PATCH的HTTP方法之一 3. getRequestParams() - 请求参数(标题),如果有的话 4. getPostParams() - post params if。如果有的话 5. parseResponse(String) - 派生类必须给出此方法的定义以解析收到的响应 6. notifyError(int) - 派生类必须给出此方法的定义,以处理通信中可能收到的错误。

package com.example.sample;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import android.os.AsyncTask;
/**
 * This class is an abstract base class for all web services.
 */
public abstract class BaseService {
    protected abstract String getUrl();
    protected abstract HttpMethods getHttpMethod();
    protected abstract ArrayList< NameValuePair > getRequestParams();
    protected abstract ArrayList< NameValuePair > getPostParams();
    protected abstract void parseResponse( String response );
    protected abstract void notifyError( int errorCode );

    public void send() {
        SendRequestTask sendRequestTask = new SendRequestTask( );
        sendRequestTask.execute( );
    }

    private class SendRequestTask extends AsyncTask< Void, Void, Integer > {
        @Override
        protected Integer doInBackground( Void... params ) {
            try {
                String url = getUrl( );
                HttpMethods method = getHttpMethod( );
                ArrayList< NameValuePair > httpParams = getRequestParams( );
                ArrayList< NameValuePair > postParams = getPostParams( );

                HttpCommunication httpCommunication = new HttpCommunication( );
                String response = httpCommunication.makeHttpRequest( url, method, httpParams, postParams );

                parseResponse( response );
            } catch ( Exception ex ) {
                ex.printStackTrace( );
                notifyError( CommunicationError.ERROR_COMMUNICATION );
            }
            return 0;
        }
    }
}

以下是从上面的类派生的示例webservice类的代码;

package com.example.sample;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
 * This is a web service class to login.
 */
public class SignIn extends BaseService {
    private final String _emailId;
    private final String _password;
    private final String _signinUrl = "http://www.example.com/login.php";

    public SignIn( String userName, String password ) {
        _emailId = userName;
        _password = null;
    }

    @Override
    protected String getUrl() {
        return _signinUrl;
    }

    @Override
    protected ArrayList< NameValuePair > getRequestParams() {
        ArrayList< NameValuePair > params = new ArrayList< NameValuePair >( );
        params.add( new BasicNameValuePair( "header1", "header1" ) );
        params.add( new BasicNameValuePair( "header2", "header2" ) );
        return params;
    }

    @Override
    protected ArrayList< NameValuePair > getPostParams() {
        ArrayList< NameValuePair > params = new ArrayList< NameValuePair >( );
        params.add( new BasicNameValuePair( "email", _emailId ) );
        params.add( new BasicNameValuePair( "password", _password ) );
        return params;
    }

    @Override
    protected HttpMethods getHttpMethod() {
        return HttpMethods.POST;
    }

    @Override
    protected void parseResponse( String response ) {
        // Parse the response here
    }

    @Override
    protected void notifyError( int errorCode ) {
        // Notify error to application
    }
}

以下是如何使用SignIn webservice;

SignIn signIn = new SignIn("abic@gmail.com", "abc123");
signIn.send();

请修改您的HttpCommunication类,如下所示。

package com.example.sample;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.apache.http.NameValuePair;

public class HttpCommunication {
    private final int CONNECTION_TIMEOUT = 10 * 1000;

    /**
     * Default Constructor
     */
    public HttpCommunication() {

    }

    public String makeHttpRequest( String strUrl, HttpMethods method, ArrayList< NameValuePair > requestParams, ArrayList< NameValuePair > postData ) throws Exception {

        HttpURLConnection connection = null;
        InputStream inputStream = null;
        URL url = null;
        String response = null;
        try {
            url = new URL( strUrl );
            connection = (HttpURLConnection) url.openConnection( );
            connection.setConnectTimeout( CONNECTION_TIMEOUT );
            connection.setReadTimeout( CONNECTION_TIMEOUT );

            if ( requestParams != null && requestParams.size( ) > 0 ) {
                for ( NameValuePair pair : requestParams ) {
                    connection.setRequestProperty( pair.getName( ), pair.getValue( ) );
                }
            }

            connection.setDoInput( true );
            connection.connect( );
            if ( method == HttpMethods.POST ) {
                OutputStream os = connection.getOutputStream( );
                // Convert post data to string and then write it to outputstream.
                String postDataStr = "test";
                os.write( postDataStr.getBytes( ) );
                os.close( );
            }

            inputStream = connection.getInputStream( );

            if ( inputStream != null ) {
                BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream, "UTF-8" ) );
                StringBuilder sb = new StringBuilder( );
                String line = null;
                while ( ( line = reader.readLine( ) ) != null ) {
                    sb.append( line + "\n" );
                }
                response = sb.toString( );
                inputStream.close( );
            }
            connection.disconnect( );
        } catch ( Exception e ) {
            if ( connection != null ) {
                connection.disconnect( );
            }
        }

        return response;
    }
}