網絡通路
ANR(應用程式無響應)
- 不能再主線程中進行耗時操作(例如通路網絡)
原因:主線程類似于一個阻塞式線程,需要保持啟動狀态,才能不斷接收各種操作消息,如果在主線程中不斷的進行耗時操作,那麼主線程就不能及時接受系統發送的各種消息,是以谷歌在安卓4.0後推出了ANR,一種系統(或者程式)保護機制,如果在主線程中進行耗時操作的話,就會給出該提示,是以不能再主線程中進行耗時操作
- 隻有在主線程中才能更新UI,子線程中不可以修改UI
問題:那麼子線程想要更新UI怎麼辦 回答:使用Handler消息機制
- Handler消息機制的原理
- Handler:消息處理器
- Message Queue: 消息隊列,主線程裡面的一個消息隊列.
- Looper : 輪詢器,檢查消息隊列裡面是否有消息.---> HandleMessage();
完整叙述Handler消息機制: 隻有在主線程中才可以更新UI,如果想在子線程中更新UI的話,可以使用Hnadler消息機制,Handler中有一個Message Queue消息隊列,這個隊列裡面有一個Looper輪詢器,他會檢查消息隊列中是否有消息,如果有消息就會通過主線程中的HandleMessage(),處理消息。
- 小案例,網絡圖檔檢視器
在editText中輸入網址,然後顯示在ImageView中 因為請求網絡是耗時操作,是以在子線程中進行,但是顯示圖檔,需要在主線程中心性,是以使用handler 步驟 - 擷取輸入的圖檔路徑
- 請求該圖檔位址
- 擷取傳回結果,然後顯示在ImageView中
代碼如下:
protected static final int SUCCESS = ;
protected static final int ERROR = ;
private EditText et_path;
private ImageView iv;
//1.得到消息處理器
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SUCCESS:
Bitmap bitmap = (Bitmap) msg.obj;
iv.setImageBitmap(bitmap);
break;
case ERROR:
Toast.makeText(MainActivity.this, "擷取圖檔失敗", 0).show();
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path = (EditText) findViewById(R.id.et_path);
iv = (ImageView) findViewById(R.id.iv);
}
/**
* 點選檢視圖檔
*
* @param view
*/
public void viewImage(viewImageView view) {
final String path = et_path.getText().toString().trim();
if (TextUtils.isEmpty(path)) {
Toast.makeText(this, "對不起,圖檔路徑不能為空", ).show();
return;
}
new Thread(){
public void run() {
//開啟新的子線程 去請求網絡 擷取資料
// 顯示這個網際網路上的圖檔
try {
// 1.得到圖檔的url路徑
URL url = new URL(path);
// 2.通過路徑打開一個http的連接配接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();// http
conn.setRequestMethod("GET");//設定請求參數為get, 預設的請求方式就是get
conn.setConnectTimeout();//設定請求伺服器的逾時時間.
// 3.得到伺服器的傳回資訊
String type = conn.getContentType();
int length = conn.getContentLength();
System.out.println("伺服器資源的長度:"+length);
System.out.println("伺服器傳回的資料類型:" + type);
int code = conn.getResponseCode(); // 200 OK 404 資源沒找到 503伺服器内部錯誤
if (code == ) {
InputStream is = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
//iv.setImageBitmap(bitmap);
//不能直接更新ui,通過發消息讓handler去更新ui
Message msg = Message.obtain();//節約了記憶體
msg.what = SUCCESS;
msg.obj = bitmap;
handler.sendMessage(msg);
is.close();
}
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what = ERROR;
handler.sendMessage(msg);
}
};
}.start();
}