Android之Http網路編程(四)

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   io   os   ar   使用   

前面幾篇博文簡單的介紹了一些常見的Http的操作,這些操作幾乎都是在新開的線程中進行的網路請求,並在日誌中列印出擷取到的網路資料。那麼,問題來了!(呃~感覺下一句是藍翔有木有?)如何在把擷取到的網路資料顯示在UI介面上呢?如果按照前幾篇博文的例子,並在主線程中直接對子線程擷取的網路資料直接進行操作就會發現一個問題,那就是在主線程中根本就擷取不到子線程得到的從伺服器返回的資料。因為,網路操作屬於耗時操作,為了不阻塞主線程而放在子線程中,當主線程中的代碼執行完後子線程未必就擷取到伺服器返回的資料了。所以,為瞭解決這樣的問題我們通常在Http的操作中加上非同步訊息機制,並且為了簡化操作對其進行簡單的封裝,加上回調機制。

 

這篇博文就以HttpClient訪問百度首頁為例子,對之前博文中的Http操作進一步的完善。

首先,先回憶一下使用HttpClient的最簡單的步驟或者說是過程:

(這裡的strurl為"http://www.baidu.com",str為從伺服器返回的資料。)

HttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet(strurl);HttpResponse response= client.execute(request);if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {String str = EntityUtils.toString(response.getEntity());}

 

下面將基於上面的這些操作來實現簡易封裝:

首先加入回調機制:

(如果對回調還不太熟悉,請參考博文《java回調機制解析》)

public interface HttpCallback {    void onSuccess(Object result);    void onFailure(Exception result);}

 

 

接下來,實現一個Request類:

這個類一共有三個屬性:

method是在該類中用enum類型限定的RequestMethod類型的對象,用於佈建要求方式。

url就是網路請求的路徑。

callback為回調介面對象,用於在網路請求中擷取到資料後將資料傳遞至調用處。

public class Request {    public RequestMethod method;    public String url;    public HttpCallback callback;    public Request(String url, RequestMethod method) {        this.method = method;        this.url = url;    }    public Request(String url) {        this.method = RequestMethod.GET;        this.url = url;    }    public enum RequestMethod {        GET, POST, DELETE, PUT    }    public void setCallBack(HttpCallback callback) {        this.callback = callback;    }    public void execute() {        RequstTask task = new RequstTask(this);        task.execute();    }}

從上面的代碼可以看出,該類的兩個建構函式,都需要傳入URL,其中一個建構函式可以佈建要求方式,另一個設定預設請求方式GET。
在該類中有一個execute()方法,在這個方法中RequestTask類繼承於AsyncTask,它的作用就是在RequestTask中進行網路請求。

 

 

RequestTask代碼如下:

public class RequstTask extends AsyncTask<Void, integer, Object> {    private Request requset;    public RequstTask(Request requset) {        this.requset = requset;    }    @Override    protected void onPreExecute() {        // TODO Auto-generated method stub        super.onPreExecute();    }    @Override    protected Object doInBackground(Void... params) {        try {            HttpResponse response = HttpClientUtils.execute(requset);            if (requset.callback != null) {                //如果進一步抽象化回調介面,使其子抽象類別能分別處理多種格式的資料(如:JSON、XML、String、File),可以更方便                //這裡直接使用返回String類型的資料                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){                    return EntityUtils.toString(response.getEntity());                }                return "請求失敗";            } else {                return null;            }                    } catch (Exception e) {            return e;        }    }    @Override    protected void onPostExecute(Object result) {        if (requset.callback != null) {            if (result instanceof Exception) {                requset.callback.onFailure((Exception) result);            } else {                requset.callback.onSuccess(result);            }        }    }    @Override    protected void onProgressUpdate(integer... values) {        // TODO Auto-generated method stub        super.onProgressUpdate(values);    }}

這個類的建構函式需要傳遞一個Request對象,會根據這個Request對象的method屬性確定請求方式、url屬性確定請求路徑,根據callback屬性的有無來判斷是否是否將擷取到的網路資料傳遞至調用介面處。
在doInBackground()中如果Request對象的callback屬性為null則返回null:

當Request對象的callback屬性不為null,則先取出伺服器返回的狀態代碼(這裡的response為伺服器返回的資訊),如果等於200(也就是HttpStatus.SC_OK)那麼就說明響應成功了。再調用getEntity()方法擷取到一個HttpEntity執行個體,然後再用EntityUtils.toString()這個靜態方法將HttpEntity轉換成字串並return。返回後的資料將傳入onPostExecute()方法中作為參數。

      if (requset.callback != null) {                //如果進一步抽象化回調介面,使其子抽象類別能分別處理多種格式的資料(如:JSON、XML、String、File),可以更方便                //這裡直接使用返回String類型的資料                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){                    return EntityUtils.toString(response.getEntity());                }                return "請求失敗";            } else {                return null;            }

在onPostExecute()中Request對象的callback屬性為null根本就沒返回。反之,doInBackground()的結果result將會傳遞至回調介面的調用處:

    if (requset.callback != null) {            if (result instanceof Exception) {                requset.callback.onFailure((Exception) result);            } else {                requset.callback.onSuccess(result);            }        }

 

 

在doInBackground()中有一句代碼:

HttpResponse response = HttpClientUtils.execute(requset);

這裡的HttpClientUtils其實就是一個簡單的封裝,其代碼如下:

public class HttpClientUtils {    public static HttpResponse execute(Request requst) throws Exception {        switch (requst.method) {        case GET:            return get(requst);        }        return null;    }    private static HttpResponse get(Request requst)            throws ClientProtocolException, IOException {        HttpClient client = new DefaultHttpClient();        HttpGet get = new HttpGet(requst.url);        HttpResponse response = client.execute(get);        return response;    }}

從代碼中可以看出,execute()和get()方法都是static類型並且傳回型別都是HttpResponse。在execute()方法中根據傳入的Request對象的method屬性結合switch語句執行相對應的網路請求方式,並返回從伺服器獲得HttpResponse類型的資訊。這個資訊在RequstTask類中被直接賦值使用。

 

 

大體的過程就是這樣了。

最後的最後,在Activity中的使用:

public class MainActivity extends Activity {    private Button btn;    private TextView tv;    private Request request;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        btn = (Button) findViewById(R.id.btn);        tv = (TextView) findViewById(R.id.tv);        request = new Request("http://www.baidu.com", RequestMethod.GET);        btn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                try {                    request.setCallBack(new HttpCallback() {                        @Override                        public void onSuccess(Object result) {                            tv.setText((String) result);                        }                        @Override                        public void onFailure(Exception result) {                            tv.setText("請求失敗");                        }                    });                } catch (Exception e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                request.execute();            }        });    }}

Activity的布局檔案如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <Button        android:id="@+id/btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="請求" />    <ScrollView        android:id="@+id/sv"        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <TextView            android:id="@+id/tv"            android:layout_width="fill_parent"            android:layout_height="fill_parent" />    </ScrollView></LinearLayout>
View Code

 

 

運行程式,效果如下:

 

 

Demo下載:http://download.csdn.net/detail/af74776/8066779

Android之Http網路編程(四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.