網(wǎng)絡(luò)圖片查看器(掌握)
確定圖片的網(wǎng)址
-
發(fā)送http請求
URL url = new URL(address); //獲取連接對象,并沒有建立連接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //設(shè)置連接和讀取超時 conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //設(shè)置請求方法,注意必須大寫 conn.setRequestMethod("GET"); //建立連接,發(fā)送get請求 //conn.connect(); //建立連接,然后獲取響應(yīng)嗎,200說明請求成功 conn.getResponseCode();
-
服務(wù)器的圖片是以流的形式返回給瀏覽器的
//拿到服務(wù)器返回的輸入流 InputStream is = conn.getInputStream(); //把流里的數(shù)據(jù)讀取出來,并構(gòu)造成圖片 Bitmap bm = BitmapFactory.decodeStream(is);
-
把圖片設(shè)置為ImageView的顯示內(nèi)容
ImageView iv = (ImageView) findViewById(R.id.iv); iv.setImageBitmap(bm);
添加權(quán)限
主線程不能被阻塞
- 在Android中,主線程被阻塞會導(dǎo)致應(yīng)用不能刷新ui界面,不能響應(yīng)用戶操作,用戶體驗將非常差
- 主線程阻塞時間過長,系統(tǒng)會拋出ANR異常
- ANR:Application Not Response;應(yīng)用無響應(yīng)
- 任何耗時操作都不可以寫在主線程
- 因為網(wǎng)絡(luò)交互屬于耗時操作,如果網(wǎng)速很慢,代碼會阻塞,所以網(wǎng)絡(luò)交互的代碼不能運行在主線程
只有主線程能刷新ui
- 刷新ui的代碼只能運行在主線程,運行在子線程是沒有任何效果的
- 如果需要在子線程中刷新ui,使用消息隊列機制
- 主線程也叫ui線程
消息隊列(重點掌握)
主線程創(chuàng)建時,系統(tǒng)會同時創(chuàng)建消息隊列對象(MessageQueue)和消息輪詢器對象(Looper)
輪詢器的作用,就是不停的檢測消息隊列中是否有消息(Message)
Looper一旦發(fā)現(xiàn)Message Queue中有消息,就會把消息取出,然后把消息扔給Handler對象,Handler會調(diào)用自己的handleMessage方法來處理這條消息
handleMessage方法運行在主線程
-
主線程創(chuàng)建時,消息隊列和輪詢器對象就會被創(chuàng)建,但是消息處理器對象,需要使用時,自行創(chuàng)建
//消息隊列 Handler handler = new Handler(){ //主線程中有一個消息輪詢器looper,不斷檢測消息隊列中是否有新消息,如果發(fā)現(xiàn)有新消息,自動調(diào)用此方法,注意此方法是在主線程中運行的 public void handleMessage(android.os.Message msg) { } };
-
在子線程中使用Handler對象往消息隊列里發(fā)消息
//創(chuàng)建消息對象 Message msg = new Message(); //消息的obj屬性可以賦值任何對象,通過這個屬性可以攜帶數(shù)據(jù) msg.obj = bm; //what屬性相當(dāng)于一個標簽,用于區(qū)分出不同的消息,從而運行不能的代碼 msg.what = 1; //發(fā)送消息 handler.sendMessage(msg);
-
通過switch語句區(qū)分不同的消息
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; } }
加入緩存圖片的功能(熟悉)
-
把服務(wù)器返回的流里的數(shù)據(jù)讀取出來,然后通過文件輸入流寫至本地文件
//1.拿到服務(wù)器返回的輸入流 InputStream is = conn.getInputStream(); //2.把流里的數(shù)據(jù)讀取出來,并構(gòu)造成圖片 FileOutputStream fos = new FileOutputStream(file); byte[] b = new byte[1024]; int len = 0; while((len = is.read(b)) != -1){ fos.write(b, 0, len); }
-
創(chuàng)建bitmap對象的代碼改成
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
每次發(fā)送請求前檢測一下在緩存中是否存在同名圖片,如果存在,則讀取緩存
獲取開源代碼的網(wǎng)站(熟悉)
code.google.com
github.com
在github搜索smart-image-view
下載開源項目smart-image-view
-
使用自定義組件時,標簽名字要寫包名
<com.loopj.android.image.SmartImageView/>
-
SmartImageView的使用
SmartImageView siv = (SmartImageView) findViewById(R.id.siv); siv.setImageUrl("http://192.168.1.102:8080/dd.jpg");
Html源文件查看器(掌握)
-
發(fā)送GET請求
URL url = new URL(path); //獲取連接對象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //設(shè)置連接屬性 conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //建立連接,獲取響應(yīng)嗎 if(conn.getResponseCode() == 200){ }
-
獲取服務(wù)器返回的流,從流中把html源碼讀取出來
byte[] b = new byte[1024]; int len = 0; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len = is.read(b)) != -1){ //把讀到的字節(jié)先寫入字節(jié)數(shù)組輸出流中存起來 bos.write(b, 0, len); } //把字節(jié)數(shù)組輸出流中的內(nèi)容轉(zhuǎn)換成字符串 //默認使用utf-8 text = new String(bos.toByteArray());
亂碼的處理
-
亂碼的出現(xiàn)是因為服務(wù)器和客戶端碼表不一致導(dǎo)致
//手動指定碼表 text = new String(bos.toByteArray(), "gb2312");
提交數(shù)據(jù)(掌握)
GET方式提交數(shù)據(jù)
-
get方式提交的數(shù)據(jù)是直接拼接在url的末尾
final String path = "http://192.168.1.104/Web/servlet/CheckLogin?name=" + name + "&pass=" + pass;
-
發(fā)送get請求,代碼和之前一樣
URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); if(conn.getResponseCode() == 200){ }
-
瀏覽器在發(fā)送請求攜帶數(shù)據(jù)時會對數(shù)據(jù)進行URL編碼,我們寫代碼時也需要為中文進行URL編碼
String path = "http://192.168.1.104/Web/servlet/CheckLogin?name=" + URLEncoder.encode(name) + "&pass=" + pass;
POST方式提交數(shù)據(jù)
post提交數(shù)據(jù)是用輸出流寫給服務(wù)器的
-
協(xié)議頭中多了兩個屬性
Content-Type: application/x-www-form-urlencoded,描述提交的數(shù)據(jù)的mimetype
-
Content-Length: 32,描述提交的數(shù)據(jù)的長度
//給請求頭添加post多出來的兩個屬性 String data = "name=" + URLEncoder.encode(name) + "&pass=" + pass; conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", data.length() + "");
-
設(shè)置允許打開post請求的流
conn.setDoOutput(true);
-
獲取連接對象的輸出流,往流里寫要提交給服務(wù)器的數(shù)據(jù)
OutputStream os = conn.getOutputStream(); os.write(data.getBytes());