主線程不能被阻塞
- 在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();
}
}
}
說明
實際開發中我們網絡請求一般用的都是第三方架構,這裡對原生的請求就不再過多的研究