天天看點

安卓基礎-day04-20180118

網絡通路
ANR(應用程式無響應)
  1. 不能再主線程中進行耗時操作(例如通路網絡)
原因:主線程類似于一個阻塞式線程,需要保持啟動狀态,才能不斷接收各種操作消息,如果在主線程中不斷的進行耗時操作,那麼主線程就不能及時接受系統發送的各種消息,是以谷歌在安卓4.0後推出了ANR,一種系統(或者程式)保護機制,如果在主線程中進行耗時操作的話,就會給出該提示,是以不能再主線程中進行耗時操作
  1. 隻有在主線程中才能更新UI,子線程中不可以修改UI
問題:那麼子線程想要更新UI怎麼辦
回答:使用Handler消息機制
  1. Handler消息機制的原理
  • Handler:消息處理器
  • Message Queue: 消息隊列,主線程裡面的一個消息隊列.
  • Looper : 輪詢器,檢查消息隊列裡面是否有消息.---> HandleMessage();
完整叙述Handler消息機制: 隻有在主線程中才可以更新UI,如果想在子線程中更新UI的話,可以使用Hnadler消息機制,Handler中有一個Message Queue消息隊列,這個隊列裡面有一個Looper輪詢器,他會檢查消息隊列中是否有消息,如果有消息就會通過主線程中的HandleMessage(),處理消息。
  1. 小案例,網絡圖檔檢視器
在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();
	}