Android開発実現HttpClientツール類およびHttpClientの3種類のタイムアウト説明【回転】

8185 ワード

独自のHttpClientツールクラスを単一モードで実現
リード
Androidの開発では、ネットワーク接続機能を使ってサーバとデータのやり取りを行うことが多いため、AndroidのSDKはApacheのHttpClientを提供し、さまざまなHttpサービスを利用するのに便利です.HttpClientをブラウザとして想像することができます.そのAPIを通じてGET、POSTリクエストを簡単に発行することができます(もちろん、その機能はこれらだけではありません).
たとえば、次の数行のコードだけで簡単なGETリクエストを発行し、応答結果を印刷できます.
try {
        //        HttpClient
        HttpClient httpclient =new DefaultHttpClient();
        //     GET  
        HttpGet request =new HttpGet("www.google.com");
        //   GET  ,            
        String response = httpclient.execute(request, new BasicResponseHandler());
        Log.v("response text", response);
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

なぜHttpClientを使用するのですか?
これはプレゼンテーションコードにすぎず,実際のプロジェクトでのリクエストと応答処理は複雑であり,コードの許容誤り性も考慮されるが,これは本編の重点ではない.コードの3行目に注意:
HttpClient httpclient =new DefaultHttpClient();
HTTPリクエストを発行する前に、HttpClientオブジェクトを作成しました.では、実際のプロジェクトでは、HTTP通信を複数の場所で必要とする可能性があります.この場合、リクエストごとに新しいHttpClientを作成する必要はありません.前に述べたように、HttpClientは小型のブラウザのようなもので、アプリケーション全体に対して、私たちは1つのHttpClientだけで十分です.ここを见て、きっとある人の心の中は思って、これは何が难しいことがあって、単例を使います!!このように:
publicclass CustomerHttpClient {
    privatestatic HttpClient customerHttpClient;
    
    private CustomerHttpClient() {
    }
    
    publicstatic HttpClient getHttpClient() {
        if(null== customerHttpClient) {
            customerHttpClient =new DefaultHttpClient();
        }
        return customerHttpClient;
    }
}

では、どこがおかしいのでしょうか.それともまだ完璧ではありませんか?
マルチスレッド!今、私たちのアプリケーションは同じHttpClientを使用してすべてのHttpリクエストを管理しています.コンカレントリクエストが発生すると、マルチスレッドの問題が発生するに違いありません.これは私たちのブラウザが1つのラベルページしかないのに複数のユーザーがいるように、Aはgoogleに、Bはbaiduに、ブラウザは忙しくて来られません.幸いなことに、HttpClientはスレッドセキュリティオブジェクトを作成するAPIを提供し、スレッドセキュリティの「ブラウザ」を迅速に入手できます.
マルチスレッドの問題の解決
publicclass CustomerHttpClient {
    privatestaticfinal String CHARSET = HTTP.UTF_8;
    privatestatic HttpClient customerHttpClient;

    private CustomerHttpClient() {
    }

    publicstaticsynchronized HttpClient getHttpClient() {
        if (null== customerHttpClient) {
            HttpParams params =new BasicHttpParams();
            //         
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params,
                    CHARSET);
            HttpProtocolParams.setUseExpectContinue(params, true);
            HttpProtocolParams
                    .setUserAgent(
                            params,
                            "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
                                    +"AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");
            //     
/*               */
            ConnManagerParams.setTimeout(params, 1000);
            /*      */
            HttpConnectionParams.setConnectionTimeout(params, 2000);
            /*      */
            HttpConnectionParams.setSoTimeout(params, 4000);
            
            //      HttpClient  HTTP HTTPS    
            SchemeRegistry schReg =new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 80));
            schReg.register(new Scheme("https", SSLSocketFactory
                    .getSocketFactory(), 443));

            //               HttpClient
            ClientConnectionManager conMgr =new ThreadSafeClientConnManager(
                    params, schReg);
            customerHttpClient =new DefaultHttpClient(conMgr, params);
        }
        return customerHttpClient;
    }
}

上記のgetHttpClient()メソッドでは、HttpClientの基本パラメータとタイムアウト設定をいくつか設定し、ThreadSafeClientConnManagerを使用してスレッドセキュリティのHttpClientを作成します.上記のコードは3種類のタイムアウト設定に言及しており,比較的混同しやすいため,ここで特に判別する.
HttpClientの3種類のタイムアウト説明
/*接続プールからの接続のタイムアウト時間*/
ConnManagerParams.setTimeout(params, 1000);

/*接続タイムアウト*/
HttpConnectionParams.setConnectionTimeout(params, 2000);

/*要求タイムアウト*/
HttpConnectionParams.setSoTimeout(params, 4000);

1行目の設定ConnectionPoolTimeout:ConnectionManagerが管理する接続プールから接続を取り出すタイムアウト時間を定義します.ここでは1秒に設定します.
2行目の設定ConnectionTimeout:ネットワークを介してサーバと接続を確立するタイムアウト時間を定義します.Httpclientパッケージでは、サーバとのsocket接続を非同期スレッドで作成します.これが、このsocket接続のタイムアウト時間です.ここでは2秒に設定します.
3行目にSocketTimeoutを設定します.これは、Socketがデータを読み込むタイムアウト時間を定義します.つまり、サーバから応答データを取得するのに待つ時間です.ここでは4秒に設定します.
  
以上の3つのタイムアウトは、C o n t i onPoolTimeoutException、C o n t i onTimeoutException、SocketTimeoutExceptionをそれぞれ放出します. 
パッケージングの簡単なPOST要求
一例のHttpClientオブジェクトがあれば、GETとPOSTリクエストを発行するためによく使われるコードもカプセル化して、ツールクラスに書くことができます.現在、POSTリクエストを発行して応答文字列を返す方法だけを実現しています.次のコードをCustomerHttpClientクラスに追加します.
privatestaticfinal String TAG ="CustomerHttpClient";

publicstatic String post(String url, NameValuePair... params) {
        try {
            //     
            List<NameValuePair> formparams =new ArrayList<NameValuePair>(); //     
for (NameValuePair p : params) {
                formparams.add(p);
            }
            UrlEncodedFormEntity entity =new UrlEncodedFormEntity(formparams,
                    CHARSET);
            //   POST  
            HttpPost request =new HttpPost(url);
            request.setEntity(entity);
            //     
            HttpClient client = getHttpClient();
            HttpResponse response = client.execute(request);
            if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                thrownew RuntimeException("    ");
            }
            HttpEntity resEntity =  response.getEntity();
            return (resEntity ==null) ?null : EntityUtils.toString(resEntity, CHARSET);
        } catch (UnsupportedEncodingException e) {
            Log.w(TAG, e.getMessage());
            returnnull;
        } catch (ClientProtocolException e) {
            Log.w(TAG, e.getMessage());
            returnnull;
        } catch (IOException e) {
            thrownew RuntimeException("    ", e);
        }

    } 

CustomerHttpClientツールクラスの使用
現在、プロジェクト全体でこのツールクラスを使用してネットワーク通信を行うビジネスコードの作成が容易になりました.次のコードでは、usernameとpasswordを使用してアカウントを登録し、新しいアカウントIDを取得する方法を示します.
final String url ="http://yourdomain/context/adduser";
    //    
    NameValuePair param1 =new BasicNameValuePair("username", "  ");
    NameValuePair param2 =new BasicNameValuePair("password", "123456");
    int resultId =-1;
    try {
        //          POST  ,     json  ,  "{userid:12}"
        String response = CustomerHttpClient.post(url, param1, param2);
        JSONObject root =new JSONObject(response);
        resultId = Integer.parseInt(root.getString("userid"));
        Log.i(TAG, "   ID:"+ resultId);
    } catch (RuntimeException e) {
        //           
        Log.w(TAG, e.getMessage());
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
    } catch (Exception e) {
        // JSon    
        Log.w(TAG, e.getMessage());
    }

締めくくり
ツールクラスを使用すると、プロジェクトでネットワーク通信コードを記述する効率が大幅に向上することがわかります.しかし、このツール類はまだ完備されていないので、皆さんの補充と誤りの矯正を歓迎して、最後に1つのツール類がHttpClientを使う最良の実践として完成することを望んでいます.(完)
転載を歓迎しますが、転載は出典を明記してください.http://www.cnblogs.com/codingmyworld/archive/2011/08/17/2141706.html