您好,登錄后才能下訂單哦!
一、網絡編程的核心步驟
? ? (1)在清單AndroidManifest.xml文件中添加INTERNET權限。
? ? (2)連接到網絡地址的代碼
???? ?第1步:創建URL ? ?
????????String?path?=?"http://192.168.17.98:8080/img/news.xml"; ????????URL?url?=?new?URL(path);
???? ?第2步:通過URL獲得連接HttpURLConnection?
????????HttpURLConnection?conn?=?(HttpURLConnection)?url.openConnection();
???? ?第3步:通過HttpURLConnection連接設置一些請求的參數
????????conn.setRequestMethod("GET");?//默認請求方式就是GET,要大寫。 ????????conn.setConnectTimeout(5);???//鏈接網絡超時時間,秒作單位。
???? ?第4步:請求響應并獲取服務器的響應碼,判斷響應碼的狀態,采用相應的動作。
????????int?code?=?conn.getResponseCode();?/*200??代表獲取服務器資源全 ?????????????????????????????????????????????????部成功?206??請求部分資源*/? ????????????????if?(code?==?200)?{ ???????????????????//解析連接的輸入流,獲取數據,進行其它操作。? ??????????????????... ????????????????}
????通過查看API發現,HttpURLConnection及其父類,沒有close這個關閉連接的方法。
二、Android中的消息機制
? ???在Android4.0之后,google工程師強制要求Android中的耗時操作(如上面的網絡訪問、拷貝
? ?大的數據)放在子線程中運行,否則程序在運行時就會報下面這個錯誤:
??????android.os.NetworkOnMainThreadException 在主線程訪問網絡
? ? ? 然而,在子線程中往往會有更新UI的操作(如改變activity中的組件的text值),但是更新UI
? ?的操作只能在主線程中完成,如果在子線程中有更新UI的動作,程序就會報以下錯誤:
???? ?android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original
?????thread that created a view hierarchy can touch its views. 只有主線程才可以更新ui
????這樣就形成了矛盾,那么如何解決這一矛盾(耗時操作不能放在UI線程,子線程不能更新UI)
????呢?解決辦法:有2種方式:
????第1種:消息機制Handler
???? ?1)在類的成員位置上創建一個Handler對象,復寫它的handleMessage(Message msg)方法。
????? ?在這個方法中獲取子線程傳遞過來的Message,然后更新UI。 ?
????????????//創建助手Handler??? ????????????private?Handler?handler?=?new?Handler(){ public?void?handleMessage(aMessage?msg)?{ ???//獲取消息的類型?? switch?(msg.what)?{ case?LOADSUCESS:????//代表獲取數據成功 ???//把數據取出來? String?content?=??(String)?msg.obj;????//要強轉 ???//顯示源碼的內容 tv_content.setText(content); break; case?LOADERROR:?????//代表獲取數據失敗? Toast.makeText(getApplicationContext(),?"訪問的資源不存在 ",?1).show(); break; case?LOADEXCEPTION: Toast.makeText(getApplicationContext(),?"服務器忙!!!",?1) .show(); break; } ?}; ?????};
?
????? 2)在子線程中調用Handler對象的sendMessage(Message msg)方法,將獲取的數據封裝到
???????Message中去。
????????????//創建message對象 ??Message?msg?=?Message.obtain();????//這種方式得到Message對象,可以減少 ??????????????????????????????????????創建Message的次數。還可以new個對象 ??msg.what?=?LOADSUCESS;????//標記Message的類型,int型。 ??msg.obj?=content;????//這個屬性可以攜帶任何數據類型 ????//發送一條消息??告訴系統我要更新ui?handleMessage方法會立刻執行 ??handler.sendMessage(msg);
? ?在Handler類的內部,有一個死循環Looper,一直在監聽Handler中的消息隊列。在子線程中一發送消息,加入Handler的消息隊列,死循環得知就取出消息發送給handMessage方法。原理圖如下:
? ?
? ?第2種:runOnUiThread(Runnnable action)方法
? ? ? ?這是Activity類的一個方法,關于這個方法,Android官方文檔說得很明白:
? ? ? ?如果當前線程是UI線程(主線程),那么action就會立即執行。如果當前線程不是UI線程,
???那么action就會放入UI線程的事件隊列,也就是說它會被UI線程所執行。那么就可以把更新UI的
? ? 方法放在這個action里面。
????? 核心代碼:
????????//更新ui runOnUiThread(new?Runnable()?{ public?void?run()?{ tv_content.setText(content); ????????} });
? ? ? ?但是在子線程一定不能更新UI嗎?答案是可以。
????? 在程序運行之后,Android系統會自動開啟一個審計系統,來監聽子線程中是否有更新UI的
? ? ?動作。如果在子線程中有更新UI的動作,很簡短很快的話,就不會被審計系統捕捉到,那么就
????不會報錯。如果用SystemLock.sleep()模擬一個即使是毫秒級的耗時操作的話,也會報錯。
???? ?
????
三、實現網絡圖片的緩存
? ???由于圖片的加載是十分的消耗流量的,所以初次加載圖片時可以將圖片保存到緩存中,再從緩
? ?存中把圖片顯示到控件上,以后每次訪問圖片的時候先去找緩存中有沒有這個圖片,緩存中如果沒
? ?有再去網絡上加載圖片至緩存。
? ? ? 首先,先得學習兩個類Base64和BitmapFactory。
???? Base6是一個實用工具類,可以將byte[]編碼成String,也可以將String解碼成byte[]。
????? ?decodeToString(byte[] input,int flags):即可將字節數組變成String。
???? BitmapFactory顧名就是處理Bitmap的工具類,它可以從各種資源包括文件、流、字節數組來
?????創建一個Bitmap對象。
?????? decodeStream(InputStream in):將流解析成Bitmap對象。
????? ?decodeFile(String path):將文件的路徑解析成Bitmap對象。
? ? ? 圖片緩存的實現流程:
? ? ?第1步:創建緩存圖片文件的File對象 ?
?????//通過Base64將圖片的url地址解碼成字節數組,再編碼為String類型。 ???????File?file?=new?File(getCacheDir(),?Base64.encodeToString(path.getBytes(),??????????????????Base64.DEFAULT));
? ? ?第2步:判斷File對象是否存在且大小是否為0.
???????if(file.exists()?&&?file.length()?>?0) ??????????{ ???? //通過BitmapFactory的解析路徑資源的方法獲取Bitmap對象 ???? ????Bitmap?bitmap?=?BitmapFactory.decodeFile(file.getAbsolutePath()); ???? //將Bitmap發送給消息助手,用于更新UI。 ???? ????Message?msg?=?Message.obtain(); ???? ????msg.obj?=?bitmap; ???? ????msg.what?=?LOADCACHE; ???? ????handler.sendMessage(msg); ???????????} ???????????else ???????????{ ???????????//連接網絡,得到網絡圖片的流,然后對象寫入到File圖片緩存文件中去。 ???????????????... ???????? ???InputStream?in?=?conn.getInputStream(); ???????????????//將流寫入緩存中 ???????? ???OutputStream?out?=?new?FileOutputStream(file); ???????? ???int?len?=?0; ???????? ???byte[]?buf?=?new?byte[1024]; ???????? ???while((len?=?in.read(buf))!=?-1?) ???????? ???{ ???????? out.write(buf,0,len); ???????? ????} ???????? ???in.close(); ???????????????????out.close(); ???????????????//讀取圖片緩存文件,得到Bitmap對象。 ???????????????//將Bitmap發送給消息助手,用于更新UI。 ????????????????????Message?msg?=?Message.obtain(); ???????? ????msg.obj?=?BitmapFactory.decodeFile(file.getAbsolutePath()); ???????? ????msg.what?=?LOADNET; ???????? ????handler.sendMessage(msg); ???????????}
?????
四、延遲與定時操作? ?
? ? ?1) Handler類本身有個方法可以實現延遲操作
?????? public final boolean postDelayed (Runnable r, long delayMillis)
????? ?官方文檔是這么說明這個方法的:
????? ?將Runnable加入消息隊列,過了指定的時間delayMillis之后運行。Runnable會運行在
?????Handler對象綁定的那個線程中。?
????????handler.postDelayed(new?Runnable()?{ ????@Override ????public?void?run()?{ tv.setText("123456"); ????} ????????},?5000);
????//上面這段代碼的handler必需是成員位置已經創建的Handler對象,直接寫new Handler會報下
???? ?面這個異常。
????
????java.lang.RuntimeException: Can't create handler inside thread that has not called
??????????????????Looper.prepare()
????? ?原因是上面這段代碼是寫在一個子線程中的,如果直接new Handler,這個Handler對象屬
????于子線程的內部成員,Runnable還是在子線程中執行的,仍然在子線程中更新UI。
? ? ?? ?當然了,Handler類還有定時操作的API,用時再去查吧。? ?
????2) Timer實現延遲操作
????? ?在JDK里,有個類Timer,可以實現延遲與定時操作,以及重復執行操作。
????? ?schedule(TimerTask?task,
long?delay)
??????????安排在指定延遲后執行指定的任務。
??????//定義一個時鐘 ???? Timer?timer?=?new?Timer(); ??????//延遲執行時鐘的run方法 timer.schedule(new?TimerTask()?{ ????@Override ????public?void?run()?{ runOnUiThread(new?Runnable()?{ @Override public?void?run()?{ tv.setText("123456"); } }); ????} },5000);
? ? ? ?
????
獲取熱點的IP地址
????https://blog.csdn.net/qq_19560943/article/details/54317932
?
獲取httpurlconnectionr的responseheader
https://www.2cto.com/kf/201306/216213.html
? ? ??
OkHttp3在加速器領域的一個錯誤
?????錯誤記錄-CLEARTEXT communication to * not permitted by network
??????https://www.jianshu.com/p/4c8dda36ab42
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。