天天看點

網絡請求詳解

主線程不能被阻塞

  • 在Android中,主線程被阻塞會導緻應用不能重新整理ui界面,不能響應使用者操作,使用者體驗将非常差
  • 主線程阻塞時間過長,系統會抛出ANR異常
  • ANR:Application Not Response;應用無響應
  • 任何耗時操作都不可以寫在主線程
  • 因為網絡互動屬于耗時操作,如果網速很慢,代碼會阻塞,是以網絡互動的代碼不能運作在主線程

隻有主線程能重新整理ui

  • 重新整理ui的代碼隻能運作在主線程,運作在子線程是沒有任何效果的
  • 如果需要在子線程中重新整理ui,使用消息隊列機制
消息隊列
  • Looper一旦發現Message Queue中有消息,就會把消息取出,然後把消息扔給Handler對象,Handler會調用自己的handleMessage方法來處理這條消息
  • handleMessage方法運作在主線程
  • 主線程建立時,消息隊列和輪詢器對象就會被建立,但是消息處理器對象,需要使用時,自行建立
    //消息隊列
    Handler handler = new Handler(){
        //主線程中有一個消息輪詢器looper,不斷檢測消息隊列中是否有新消息,如果發現有新消息,自動調用此方法,注意此方法是在主線程中運作的
        public void handleMessage(android.os.Message msg) {
    
        }
    };
               
  • 在子線程中往消息隊列裡發消息
    //建立消息對象
    Message msg = new Message();
    //消息的obj屬性可以指派任何對象,通過這個屬性可以攜帶資料
    msg.obj = bm;
    //what屬性相當于一個标簽,用于區分出不同的消息,進而運作不能的代碼
    msg.what = 1;
    //發送消息
    handler.sendMessage(msg);
               
  • 通過switch語句區分不同的消息
    public void handleMessage(android.os.Message msg) {
        switch (msg.what) {
        //如果是1,說明屬于請求成功的消息
        case 1:
            ImageView iv = (ImageView) findViewById(R.id.iv);
            Bitmap bm = (Bitmap) msg.obj;
            iv.setImageBitmap(bm);
            break;
        case 2:
            Toast.makeText(MainActivity.this, "請求失敗", 0).show();
            break;
        }       
    }
               

Android中的Http請求

Android中提供了兩種執行網絡請求的方式,一種是使用apache的HttpClient,另一個是用java的HttpURLConnection。
           

HttpClient

在Android開發中,android sdk附帶了apache的httpclient,可以使用它的對象來執行get和post調用。一般使用步驟如下:

使用DefaultHttpClient類執行個體化HttpClient對象;
建立HttpGet或HttpPost對象,将要請求的URL通過構造方法傳入HttpGet或HttpPost對象;
調用execute方法發送Get或Post請求,并傳回HttpResponse對象;
通過HttpResponse接口的getEntity方法傳回響應資訊,并通過相應的處理。
           

HttpURLConnection

android 2.2版本及之前用HttpClient,而在2.3版本之後,HttpURLConnection則是最佳選擇。
它的壓縮和緩存機制可以有效地減少網絡通路的流量,在Android 6.0中,HttpClient庫已經被移除。
           

*

private void sendRequest(String url) throws IOException {
InputStream is = null;
try {
    URL newUrl = new URL(url);
    HttpURLConnection conn = (HttpURLConnection) newUrl.openConnection();
    // 設定讀取逾時為10秒
    conn.setReadTimeout(10000);
    // 設定連結逾時為15秒
    conn.setConnectTimeout(15000);
    // 設定請求方式
    conn.setRequestMethod("POST");
    // 接收輸入流
    conn.setDoInput(true);
    // 啟動輸入流,當需要傳遞參數時需要開啟
    conn.setDoOutput(true);
    // 添加Header
    conn.ssetRequestProperty("Connection", "Keep-Alive");
    // 添加請求參數
    List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
    paramsList.add(new BasicNameValuePair("username", "name"));
    paramsList.add(new BasicNameValuePair("pwd", "pwd"));
    writeParams(conn,getOutputStream(), paramsList);

    conn.connect();

    is = conn.getInputStream();

    ...

} finally {
    if (is != null) {
        is.close();
    }
}

}
           

說明

實際開發中我們網絡請求一般用的都是第三方架構,這裡對原生的請求就不再過多的研究