Androidもアーキテクチャの3つ:シンプルなファクトリモデル最適化ネットワークリクエスト


悲しいことに、私たちは「Androidもアーキテクチャの2つ:単例モードアクセスネットワーク」でhttpConnectでネットワークにアクセスし、正常にデータを取得することができますが、ボスはできます.技術が生まれて、彼は私に再びhttpClientでネットワークデータを取得するように要求しました.子供靴たち、頭が爆発しているのではないでしょうか.あなたもこのような状況やこのような状況に遭遇したことがありますか?
変化を抱擁して、今から始めましょう.前の文章「Androidもアーキテクチャの2:単例モードアクセスネットワーク」では、単例モードを使用することを学びました.単例モードは一般的にプログラムに関する問題を解決し、ビジネスロジックとは関係ありません.今日から、ビジネスに関する設計モードを学び、変化を抱擁し始めました.ビジネスやニーズの変化を馬に乗せてあげましょう...
今日、この文章を通じて、以下の知識点を学びました.
1、簡単な工場モード、apiインタフェースに基づいて開発した作業モードをマスターし、インタフェースの特徴は挿抜可能で、クライアントデータに影響しない.
2、httpclientフレームワークでhttpデータを要求することをマスターし、androidのhttpclientフレームワークの詳細な知識点に関連し、例えばhttpclient自動再接続メカニズム、接続自動解放など
3、サブスレッドでメインスレッドを更新するandroidの基礎知識を学ぶ
まず、プロジェクトのディレクトリ構造を見てみましょう.
先ほど述べたように、インタフェースベースの開発は挿抜可能であるべきであり、サービス側(httpパッケージの下のクラス)がどのように変化してもクライアント(clientActivity)の使用に影響を与えず、サービス側が機能を追加または修正する際にクライアント(clientActivity)コードを修正することはできないということです.
まずAndroidManifestを見てみましょうxmlのコード、簡単です



    

    
        
            
                

                
            
        
    

       
	
	
には主にネットワークへのアクセス権限が追加されています

	

次にレイアウトファイルmainを見てみましょう.xmlも、とても簡単です.ネットワークのhttpデータを表示するためのtextview



     


次に、ネットワークモジュールにインタフェースを定義します.このインタフェースは主にネットワークを読み取るために使用され、簡単です.1つの方法しかありません.
package com.yangfuhai.simplefactory.http;
/**
 * @title http      
 * @description   
 * @company         (www.tsz.net)
 * @author michael Young (www.YangFuhai.com)
 * @version 1.0
 * @created 2012-8-21
 */
public interface HttpApi {
	
	public String getUrlContext(String strUrl);

}

次に2つのクラスがあり、このインタフェースを実装し、1つはHttpURLConnectionで実装され、1つはhttpclientで実装されます.コードは次のとおりです.
HttpUtils:
package com.yangfuhai.simplefactory.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import android.util.Log;

/**
 * @title Http     
 * @description   http  ,    
 * @company         (www.tsz.net)
 * @author michael Young (www.YangFuhai.com)
 * @version 1.0
 * @created 2012-8-19
 */
public class HttpUtils implements HttpApi{
	private static final String DEBUG_TAG = "HttpUtils";
	private HttpUtils() {} //     ,        
	
	private static HttpUtils httpUtils = null; 
	
	//                   
	public static HttpUtils get(){
		if(httpUtils == null)
			httpUtils = new HttpUtils();
		return httpUtils;
	}
	
	/**
	 *     url   
	 * @param strUrl
	 * @return
	 */
	@Override
	public String getUrlContext(String strUrl){
		 InputStream is = null;
		    int len = 500;
		        
		    try {
		        URL url = new URL(strUrl);
		        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		        conn.setReadTimeout(10000 /* milliseconds */);
		        conn.setConnectTimeout(15000 /* milliseconds */);
		        conn.setRequestMethod("GET");
		        conn.setDoInput(true);
		        conn.connect();
		        int response = conn.getResponseCode();
		        Log.d(DEBUG_TAG, "The response is: " + response);
		        is = conn.getInputStream();
		        
		        //      500(len=500)  ,   
		        //           conn.getContentLength()   len
		        String contentAsString = readInputStream(is, len);
		        return contentAsString;
		       
		    } catch (Exception e) {
		    	e.printStackTrace();
		    } finally {
		        if (is != null) {
		            try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		        } 
		    }
		    return null;
	}
	
	/**
	 *    InputStream   
	 * @param stream
	 * @param len
	 * @return
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	private String readInputStream(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
	    Reader reader = null;
	    reader = new InputStreamReader(stream, "UTF-8");        
	    char[] buffer = new char[len];
	    reader.read(buffer);
	    return new String(buffer);
	}

}

HttpClientUtils.JAvaクラス:
package com.yangfuhai.simplefactory.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import android.util.Log;

/**
 * @title HttpClient      
 * @description   
 * @company         (www.tsz.net)
 * @author michael Young (www.YangFuhai.com)
 * @version 1.0
 * @created 2012-8-21
 */
public class HttpClientUtils implements HttpApi {

	private static final String DEBUG_TAG = "HttpClientUtils";
	private static final String CHARSET_UTF8 = "UTF-8";

	private HttpClientUtils() {} //      ,        

	private static HttpClientUtils httpClientUtils = null;

	/**
	 *                    
	 * @return
	 */
	public static HttpClientUtils get() {
		if (httpClientUtils == null)
			httpClientUtils = new HttpClientUtils();
		return httpClientUtils;
	}
	
	

	@Override
	public String getUrlContext(String strUrl) {
		String responseStr = null;//     ,    
		DefaultHttpClient httpClient = null;
		HttpGet httpGet = null;
		try {
			strUrl = urlEncode(strUrl.trim(), CHARSET_UTF8);
			httpClient = getDefaultHttpClient(null);
			httpGet = new HttpGet(strUrl);
			responseStr = httpClient.execute(httpGet, strResponseHandler);
		} catch (ClientProtocolException e) {
			Log.e(DEBUG_TAG, e.getMessage());
		} catch (IOException e) {
			Log.e(DEBUG_TAG, e.getMessage());
		} catch (Exception e) {
			Log.e(DEBUG_TAG, e.getMessage());
		} finally {
			abortConnection(httpGet, httpClient);
		}
		return responseStr;
	}

	
	
	/**
	 *   http   ,        
	 * 
	 * @param str
	 * @param charset
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static String urlEncode(String str, String charset)
			throws UnsupportedEncodingException {
		Pattern p = Pattern.compile("[\u4e00-\u9fa5]+");
		Matcher m = p.matcher(str);
		StringBuffer b = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(b, URLEncoder.encode(m.group(0), charset));
		}
		m.appendTail(b);
		return b.toString();
	}

	
	
	/**
	 *                
	 */
	private static HttpRequestRetryHandler requestRetryHandler = new HttpRequestRetryHandler() {
		//         
		public boolean retryRequest(IOException exception, int executionCount,
				HttpContext context) {
			//       , Http             3 
			if (executionCount >= 3) {
				// Do not retry if over max retry count
				return false;
			}
			if (exception instanceof NoHttpResponseException) {
				// Retry if the server dropped connection on us
				return true;
			}
			if (exception instanceof SSLHandshakeException) {
				// Do not retry on SSL handshake exception
				return false;
			}
			HttpRequest request = (HttpRequest) context
					.getAttribute(ExecutionContext.HTTP_REQUEST);
			boolean idempotent = (request instanceof HttpEntityEnclosingRequest);
			if (!idempotent) {
				// Retry if the request is considered idempotent
				return true;
			}
			return false;
		}
	};

	
	//   ResponseHandler      ,HttpClient  ResponseHandler          ,
	//          
	private static ResponseHandler strResponseHandler = new ResponseHandler() {
		//        
		public String handleResponse(HttpResponse response)
				throws ClientProtocolException, IOException {
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String charset = EntityUtils.getContentCharSet(entity) == null ? CHARSET_UTF8
						: EntityUtils.getContentCharSet(entity);
				return new String(EntityUtils.toByteArray(entity), charset);
			} else {
				return null;
			}
		}
	};
	
	
	

	/**
	 *   DefaultHttpClient  
	 * 
	 * @param charset
	 * @return
	 */
	private static DefaultHttpClient getDefaultHttpClient(final String charset) {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		// httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
		// HttpVersion.HTTP_1_1);
		//      (             ,       ~~~)
		// httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");
		// httpclient.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,Boolean.FALSE);
		
		//     
		httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
		//     
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,5000);
		httpclient.getParams().setParameter(
				CoreProtocolPNames.HTTP_CONTENT_CHARSET,
				charset == null ? CHARSET_UTF8 : charset);
		httpclient.setHttpRequestRetryHandler(requestRetryHandler);
		return httpclient;
	}

	/**
	 *   HttpClient  
	 * 
	 * @param hrb
	 * @param httpclient
	 */
	private static void abortConnection(final HttpRequestBase httpRequestBase,
			final HttpClient httpclient) {
		if (httpRequestBase != null) {
			httpRequestBase.abort();
		}
		if (httpclient != null) {
			httpclient.getConnectionManager().shutdown();
		}
	}

}

次に、工場類を見てみましょう.
package com.yangfuhai.simplefactory.http;

/**
 * @title Http    
 * @description   http  
 * @company         (www.tsz.net)
 * @author michael Young (www.YangFuhai.com)
 * @version 1.0
 * @created 2012-8-21
 */
public class HttpFactory {
	
	private static final int HTTP_CONFIG= 1 ;//http    ,0 httpConnect,1 httpclient
	
	public static HttpApi getHttp(){
		if(HTTP_CONFIG == 0)
			return HttpUtils.get();
		else if(HTTP_CONFIG == 1)
			return HttpClientUtils.get();
		
		return null;
	}

}

ファクトリクラスでは、一般的にhttp内部モジュールを取得するには、クライアントから指定されたモジュールを取得するモードがいくつかあります.1つは、HttpFactory内部の論理によって実現され、より需要または他の特定の条件が異なるインタフェースに戻ることがあります.1つは、プロファイルを通じて取得されます.例えば、ファイルを読み込むなどです.ここでは、ネットワークプロファイルを読み込む形式を簡単にシミュレートし、HTTP_を通じてCONFIGの構成は異なるhttpモジュールを返し、httpUrlConnectionの方式でもhttpclientの形式でも、簡単にここで構成すればいいのですが、ここでどのように修正してもクライアント(httpclient)のコードには影響しません.いつボスが血を流してicp/ip、socketの形式でネットワーク情報を取得するには、このパッケージ(com.yangfuhai.simplefactory.http)の下にsocketがネットワーク情報を取得するクラスを追加するだけで、クライアント(clientActivity)のコードを変更する必要はありません.(拍手XXXXXX)と同時に、httpUrlConnectionまたはhttpClientのクラスを削除することができ、クライアントには少しも影響しません(挿抜可能).
クライアント・コードは次のとおりです.
package com.yangfuhai.simplefactory;

import com.yangfuhai.simplefactory.http.HttpFactory;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

/**
 * @title     
 * @description     
 * @company         (www.tsz.net)
 * @author michael Young (www.YangFuhai.com)
 * @version 1.0
 * @created 2012-8-19
 */
public class ClientActivity extends Activity {
	
	TextView mTv;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTv = (TextView) findViewById(R.id.textView);
        
        mTv.setText("    www.devchina.com  。。。");
        new Thread(new Runnable() {
			
			@Override
			public void run() {
				final String strContext = HttpFactory.getHttp().getUrlContext("http://www.devchina.com");
				runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						if(strContext!=null)
							mTv.setText(strContext);
						else
							mTv.setText("    。。。");
					}
				});
			}
		}).start();
        
    }
    
    
}

ここで主に強調するのは、この行のコードです.
final String strContext = HttpFactory.getHttp().getUrlContext("http://www.devchina.com");
ここでは工場を通じてHttpApiを取得しなければなりません.そうしないと、clientActivityクラスにコードが侵入し、挿抜可能になりません.
OK、成功しました.
ソースのダウンロードアドレス:http://download.csdn.net/detail/michael_yy/4516372eclipseを直接インポートすれば使えます~~~
皆さん、よろしくお愿いします.http://www.devchina.com/またはhttp://blog.csdn.net/michael_yyあ、ありがとう.
注目ありがとうございます.私は引き続きブログで経典の23中モードの中でandroidの実際のプロジェクトの中で柔軟に運用することを説明しました.次の「Androidもアーキテクチャの4:ゲートモード解析で取得したhtmlコード」に注目してください.