AndroidHttpClient和HttpEntity詳解


AndroidHttpClient結構:

public final class

AndroidHttpClient

extends Object
implements HttpClient

前言:這類其實是Google對阿帕奇的HttpClient的一個封裝,一些默認屬性有android做了一些優化。

   然后阿帕奇的HttpClient是對java中HttpUrlConnection的一個封裝,感覺阿帕奇封裝的還是不錯的,

   特別是其中的HttpEntity,很強大也很好用,能在android手機上上傳百M的文件到服務器,還是不錯的。

一:AndroidHttpClient的使用方式

  1.創建AndroidHttpClient對象

AndroidHttpClient c = AndroidHttpClient.newInstance("");

   AndroidHttpClient只能通過以上方法建立,其中的參數好像是設置代理的,如果沒有置空即可。

  2.使用開啟cookies

  AndroidHttpClient默認情況下是關閉cookies的,開啟的方法如下

  AndroidHttpClient c = AndroidHttpClient.newInstance("");
  BasicHttpContext context = new BasicHttpContext();
  context.setAttribute(ClientContext.COOKIE_STORE, new BasicCookieStore());
  try {
    c.execute(null, context);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

  其中的context在client發送的請求的時候,同時發送即可。發送請求方法的第一個參數,很重要,下面詳解。

二:HttpUriRequest使用

  1.上面的c.execute(null, context);第一個參數即為HttpUriRequest,用於封裝請求信息的。

  HttpUriRequest提供了兩個使用的子類,相信你閉着眼睛也能猜到,沒錯!就是HttpGet和HttpPost。

  2.ok,我們先來看看,HttpGet是怎么用的。

  題外話,其實從這個方法的名字上就能看出來,get嘛,

  就是獲取的得到的意思,所以如果你想從服務器獲取什么數據,就多用用他吧。

  HttpGet提供了三個構造函數:

  ——HttpGet()

  ——HttpGet(URI uri)

  ——HttpGet(String uri)

  看上面的最后兩個構造方法,你應該能猜到那個參數的意義了,就是想要

  獲取文件的地址!其實第一個雖然沒有提供一個地址,但是HttpGet有個

  方法可以設置資源地址:HttpGet.setURI(URI uri);

  看下他的具體初始化方式:

    方式一:

 

        try {
            final String _URI = "www.baidu.com";
            HttpGet requestGet = new HttpGet();
            requestGet.setURI(new URI(_URI));
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

 

    方式二:

        try {
            final String _URI = "www.baidu.com";
            HttpGet requestGet = new HttpGet(new URI(_URI));
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    方式三:

        final String _URI = "www.baidu.com";
        HttpGet requestGet = new HttpGet(_URI);

  3.好了,當創建好了HttpGet對象之后,就可以將其放入AndroidHttpClient訪問了。

  有人說使用Get方式訪問的時候,能不能在后面添加用戶名和密碼什么的,其實加不加

  都可以,因為在服務器那邊獲取的方式是一樣的,但是我覺得如果有參數的話,還是不要

  直接加在資源地址后面吧,因為我感覺太難看了。。。看起來不整潔,哈哈。

  那有人說了,那怎么有參數的時候怎么辦呢?下面就給你解決的方案,HttpPost閃亮登場!

  4.HttpPost這個東西,其實最NB的地方是他能放入一個實體(Entity)發送到服務器,這個

  實體能夠封裝各種數據,將想發送的數據封裝到Entity中,然后調用HttpPost的setEntity方法

  將實體放入其中,然后發送請求就行了。所以下面就好講解一下Entity的都能封裝什么類型的數據。

  HttpPost的初始化方式和HttpGet一樣的,就是將HttpGet換成HttpPost就行了。

三:HttpEntity講解(本博文的重點)

  1.有的同學可能會覺得,看博文文字太多看的很是無聊,來張圖片多好。既然大家有着要求,那就滿足你。

  要是覺得圖片看着不是清晰,可以將圖片拖拽到桌面,慢慢欣賞。

  2.上面的圖片顯示了HttpEntity的大致結構,interface和abstract我就不多說了,

  其實也沒什么說的,就是定義了一些方法,但是還沒實現,等着之后的class來具體實現的,

  打個比喻,interface就是項目經理,class就是咱們這些**了,所以還是來說說我們吧。

  ——InputStreamEntity:他就是將一個IO流封裝到實體中,這個東西很NB,經過我的實測,

  能發送百M的數據到服務器,而且不是OOM(內存溢出),之前做一個視頻拍攝,然后上傳的

  項目的時候,就遇到過視頻上傳的時候會有OOM問題,后來用分割上傳的方式解決了,但是直

  到發現這個方法的時候,發現阿帕奇已經給准備好了,還得多看書啊。

  我這里是讀取的assets下的一個文件,將其轉換為io流,然后放入了實體中。在new這個實體的

  時候,需要提供一個int參數,這個參數的數值可以小於或等於IO流的大小,否則會報錯,當參數

  的數值小於IO的大小時,會截取上傳IO,比如IO流的內容是阿拉伯數字 1到10,而參數數值你用了5

  那服務器只能接收到1 2 3 4 5.

        try {
            // 讀取assets中的文件將其轉換為io流
            InputStream is = getActivity().getAssets().open("Text.xml");
            mEntitys.add(new InputStreamEntity(is, is.available()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

  ——ByteArrayEntity:將byte數組封裝到實體中,有的時候你可能獲取到了一個byte對象,而不是io對象,

  所以直接使用這個方法就可以將byte封裝到實體中,而不用轉換一下。

        try {
            // 讀取assets中的文件將其轉換為io流
            InputStream is = getActivity().getAssets().open("Text.xml");
            // 定義一個字節數組封裝io流
            byte[] b = new byte[is.available()];
            // 將io讀入到數組中
            is.read(b);
            mEntitys.add(new ByteArrayEntity(b));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

  ——StringEntity:這個實體還是比較使用的,他能直接將一個字符串封裝到實體中,我看過

  有人用這個東西去發送圖片,就是將圖片轉成byte,然后在轉成Base64編碼的數據,再添加到

  這個實體中,其實我感覺這個就是放字符串的,就不要將圖片什么的,放進來了,畢竟還有專門

  放文件的實體呢對吧?

        try {
            // 創建一個字符串
            String str = "Hello world";
            mEntitys.add(new StringEntity(str));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

  ——UrlEncodedFormEntity:將請求的內容進行格式化了,其實這個方法同時簡化的客戶端發送,

  也簡化了服務器端獲取,服務器通過getParameters(String name)即可獲取到傳送來的信息。

  方便的原因是將發送的信息鍵值對化了,鍵值對,你懂得,就是一個Key對應一個Value唄,所以客戶端

  需要創建一個鍵值對對象即:NameValuePair。而UrlEncodedFormEntity為了一次能發送多個鍵值對,

  參數采用了集合的方式:List<NameValuePair>。

        /**
         * 服務器端,只需要使用getParameters(String name)即可獲得屬性值
         */
        try {
            // post請求,需要一個K-V集合數組,來保存請求的信息,並將其放去請求實體中
            List<NameValuePair> postParameters = new ArrayList<NameValuePair>();
            // 添加屬性對
            postParameters.add(new BasicNameValuePair("name", "android"));
            mEntitys.add(new UrlEncodedFormEntity(postParameters));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

  ——SerializableEntity:這個東西JB太強大了,不好意思爆粗口了,因為真的很NB,相信很多朋友在獲取服務器,

  或是上傳東西到服務器的時候,都遇到這樣的問題,比如獲取用戶列表,有很多用戶,通常是服務器返回xml或是json,

  然后我們再去解析,生成一個JavaBean對象,對吧,然后在創建一個集合將這些對象放進去,很是繁瑣,特別是解析的時候,

  可是如果你使用SerializableEntity這個實體的時候,你會發現,生活原來如此美好,因為你可以直接將序列化的對象放入實體中,

  然后發送,客戶端或是服務器可以直接接受這個對象!聽明白了嗎?你不需要解析什么xml或是json,直接就能獲取到這個對象了!

  是不是很NB,但是NB需要有前提的,就是你的服務器得是Java的,所以和IOS平台交互的時候,還得需要json什么的。。。。

  *有一點一定要注意,使用他的時候,被序列化的對象所在包的包名,服務器和客戶端必須一致,必須哦,其實可以做一個jar包,然后

  服務器和客戶端一起使用。

package com.xhm.Test.Http;

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
        /**
         * 在使用這個實體的時候要注意,對象的bean所在的包名要是服務器上的一致,否則會有問題。
         */
        try {
            // 創建對象
            Student student = new Student();
            student.setName("Name");
            student.setAge(11);
            mEntitys.add(new SerializableEntity(student, true));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

  ——FileEntity:這個也真心NB,直說吧,我將一個450M的rmvb的電影成功上傳的服務器上了,服務器正常打開觀看。

  媽媽再也不同擔心我的OOM問題了。而且這個使用起來還很簡單,只要提供文件的路徑和文件類型就行了。

        /**
         * 這個實體,能夠封裝一些比較大的實體,比如上百M的文件等
         * 
         * 上傳的時候,注意本demo沒有做進度條,在成功上傳之后,會返回上傳文件的大小
         */
        // 創建文件路徑,這個視頻是在SD卡中的,大概有50M大小
        File file = new File("/sdcard/DCIM/dashipin.mp4");
        mEntitys.add(new FileEntity(file, "*/*"));

  ——EntityTemplate:說實話,這個實體我還不清楚,究竟怎么去使用,或是應用什么場景,反正他有點  

  特別,因為需要一個ContentProducer對象來初始化。

        // 創建ContentProducer對象
        ContentProducer producer = new ContentProducer() {

            @Override
            public void writeTo(OutputStream outstream) throws IOException {
                // TODO Auto-generated method stub
                Writer writer = new OutputStreamWriter(outstream);
                writer.write("hello");
                writer.write("world");
                writer.flush();
                writer.close();
            }
        };
        mEntitys.add(new EntityTemplate(producer));

好了上面就是HttpEntity的一些東西,有什么不對的地方,希望批評指正!謝謝。

四:里面使用到的一些方法

  1.執行請求和解析反饋的結果

/**
     * 執行post網絡訪問
     * 
     * @param entity
     *            請求實體
     */
    private void executePost(final HttpPost request, final HttpEntity entity) {
        try {
            request.setEntity(entity);
            // 連接服務器,並獲得反饋的response
            mResponse = mClient.execute(request);
            // 從反饋的response中獲得輸入流
            BufferedReader mReader = new BufferedReader(new InputStreamReader(
                    mResponse.getEntity().getContent()));
            Message msg = new Message();
            msg.obj = "UpLoad請求\n" + BR2SB(mReader).toString();
            mHandler.sendMessage(msg);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    /**
     * 將BufferedReader轉換為StringBuffer
     * 
     * @param br
     * @throws IOException
     */
    protected StringBuffer BR2SB(BufferedReader br) throws IOException {
        StringBuffer sb = new StringBuffer("");
        String line = null;
        while ((line = br.readLine()) != null) {
            sb.append(line + "\n");
        }
        return sb;
    }
        mHandler = new Handler(new Callback() {

            @Override
            public boolean handleMessage(Message msg) {
                // TODO Auto-generated method stub
                mTextView.setText(msg.obj.toString());
                return false;
            }
        });

提示:因為android為了安全在3.0之后不允許將HTTP請求放在主線程中,所以必須使用Thread,所以這里也使用的handler來發送http反饋的信息!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM