手機(jī)的優(yōu)勢(shì)是攜帶方便烘豹,可以隨時(shí)打開瓜贾,而且手機(jī)通常總是處于聯(lián)網(wǎng)狀態(tài)的携悯,所以網(wǎng)絡(luò)支持對(duì)于手機(jī)很重要祭芦。而且Java的網(wǎng)絡(luò)編程完全適用于Android網(wǎng)絡(luò)編程。
一.網(wǎng)絡(luò)請(qǐng)求
1.URL
在真正學(xué)習(xí)網(wǎng)絡(luò)請(qǐng)求之前有必要了解一下什么是URL憔鬼,URL的英文全拼是Uniform Resource Locator龟劲,翻譯過來為統(tǒng)一資源定位器,大概意思就是URL是指向互聯(lián)網(wǎng)資源的指針轴或。
這里說的資源可以是文件或目錄昌跌,也可以是對(duì)象的引用,例如對(duì)數(shù)據(jù)庫(kù)或搜索引擎的查詢照雁。
URL的組成:協(xié)議名蚕愤、主機(jī)、端口和資源饺蚊。即滿足如下格式:
protocol://host:port/resourceName
例如 google的URL地址:
https://www.google.com
URL類提供了多個(gè)構(gòu)造器用于創(chuàng)建URL對(duì)象萍诱,一旦獲得了URL對(duì)象之后,就可以訪問該URL對(duì)象對(duì)應(yīng)的資源了污呼。
2.Http網(wǎng)絡(luò)請(qǐng)求
Android中的Http網(wǎng)絡(luò)請(qǐng)求有兩種方式:
- HttpURLConnection
- HttpClient(已不推薦使用)
既然HttpClient已被棄用裕坊,那就用HttpURLConnection。
HttpURLConnection繼承了URLConnection曙求,可用于向指定網(wǎng)站發(fā)送GET請(qǐng)求碍庵、POST請(qǐng)求。提供了一下方法:
- HttpURLConnection openConnection():返回一個(gè)HttpURLConnection對(duì)象悟狱,表示到URL所引用的遠(yuǎn)程對(duì)象的連接静浴。
- int getResponseCode():獲取服務(wù)器的響應(yīng)代碼。例如:200表示服務(wù)器成功響應(yīng)挤渐,404表示沒響應(yīng)苹享。
- String getResponseMessage():獲取服務(wù)器的響應(yīng)消息。
- String getRequestMethod():獲取發(fā)送請(qǐng)求的方法。
- void setRequestMethod():設(shè)置發(fā)送請(qǐng)求的方法得问。
- void setConnectTimeout():設(shè)置連接超時(shí)時(shí)間囤攀。
- void setReadTimeout():設(shè)置讀取超時(shí)時(shí)間。
下邊寫一個(gè)請(qǐng)求百度API獲取全國(guó)城市的方法來使用上面提到的方法宫纬。代碼如下:
public void requestCityData(final String urlString) {
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.connect();
if (connection.getResponseCode() == 200) {
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
reader.close();
String result = builder.toString();
Message msg = new Message();
msg.what = 0;
msg.obj = result;
handler.sendMessage(msg);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
從以上代碼可以看出請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的方法可以分為以下步驟:
- 創(chuàng)建URL對(duì)象url焚挠。
- 通過url.openConnection()獲取HttpURLConnection對(duì)象connection。
- 設(shè)置請(qǐng)求方式漓骚、連接延遲蝌衔、讀取延遲、連接蝌蹂。
- 通過connection.getResponseCode()獲取響應(yīng)碼來判斷是否連接成功噩斟。
- 如果連接成功,接下來的讀取文件和Java的讀文件操作一樣孤个。
- 由于請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的操作屬于耗時(shí)操作剃允,所以應(yīng)該把整個(gè)請(qǐng)求操作放在了子線程(處理異步數(shù)據(jù)有兩種方式:handler和AsyncTask,這里用handler進(jìn)行實(shí)現(xiàn)齐鲤,下一篇中的利用多線程下載會(huì)用AsyncTask)斥废,最后把請(qǐng)求到的數(shù)據(jù)通過handler.sendMessage()方法發(fā)送到主線程,在handler中的handleMessage()方法中對(duì)請(qǐng)求到的數(shù)據(jù)進(jìn)行處理给郊。handler代碼如下:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String cityData = msg.obj.toString();
Log.d("CityActivity", cityData);
break;
}
}
};
這里的handler只是簡(jiǎn)單的打印了一下請(qǐng)求到的數(shù)據(jù)营袜。
到目前為止,還不算請(qǐng)求完成丑罪,因?yàn)檫@里用到了網(wǎng)絡(luò)荚板,要想獲取網(wǎng)絡(luò)上的數(shù)據(jù),該應(yīng)用必須有請(qǐng)求網(wǎng)絡(luò)的權(quán)限吩屹,在AndroidManifest.xml中加入網(wǎng)絡(luò)權(quán)限即可跪另。
<uses-permission android:name="android.permission.INTERNET" />
二.解析xml
如果請(qǐng)求到的數(shù)據(jù)為xml類型的,就需要把xml類型的數(shù)據(jù)解析成我們想要的類型或從xml類型的數(shù)據(jù)中解析出我們想要的數(shù)據(jù)煤搜。
解析xml類型數(shù)據(jù)有兩種方式:
- SAX:基于事件驅(qū)動(dòng)的解析(解析器+事件處理器)免绿,較復(fù)雜。
- PULL
- DOM:基于文件流擦盾。
SAX嘲驾、PULL是一個(gè)標(biāo)簽一個(gè)標(biāo)簽讀,分段加載迹卢;DOM是整個(gè)文件讀取出來辽故,然后加載。
1.SAX
利用SAX解析如下xml中的id腐碱、url以及item text誊垢。
<?xml version="1.0" encoding="utf-8"?>
<web>
<item id = "0" url = "http://www.baidu.com" >百度</item>
<item id = "1" url = "http://www.sogou.com" >搜狗</item>
<item id = "2" url = "http://www.sohu.com" >搜狐</item>
</web>
先新建一個(gè)SAXParseHandler類繼承自DefaultHandler,并實(shí)現(xiàn)startDocument()、startElement()喂走、characters()殃饿、endElement()、endDocument()這五個(gè)方法芋肠。
public class SAXParseHandler extends DefaultHandler {
private List<WebURL> mWebURLs;
private WebURL mWebURL;
private boolean state = false;
@Override
public void startDocument() throws SAXException {
mWebURLs = new ArrayList<>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
mWebURL = new WebURL();
if (TextUtils.equals(localName, "item")){
for (int i = 0; i < attributes.getLength(); i++) {
if (TextUtils.equals(attributes.getLocalName(i), "id")){
mWebURL.setmID(Integer.parseInt(attributes.getValue(i)));
}else if (TextUtils.equals(attributes.getLocalName(i), "url")){
mWebURL.setmUrl(attributes.getValue(i));
}
}
state = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = String.valueOf(ch, start, length);
if (state) {
mWebURL.setmContent(content);
state = false;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (TextUtils.equals(localName, "item")){
mWebURLs.add(mWebURL);
}
}
@Override
public void endDocument() throws SAXException {
}
}
以上代碼中startDocument()表示解析到最外層的標(biāo)簽乎芳,進(jìn)行一些初始化操作,startElement()表示解析到子標(biāo)簽帖池,通過attributes來獲取該標(biāo)簽的屬性id和url秒咐,characters()表示子標(biāo)簽開始標(biāo)簽和結(jié)束標(biāo)簽中間的內(nèi)容,在這里通過轉(zhuǎn)換ch可以獲取到碘裕,endElement()表示結(jié)束子標(biāo)簽,在這個(gè)方法中將獲取到的信息進(jìn)行保存攒钳,endDocument()表示解析結(jié)束帮孔。
SAXParseHandler類將xml的每一個(gè)標(biāo)簽進(jìn)行了遍歷,接下來就是通過SAX解析器進(jìn)行解析了不撑。解析代碼如下:
private void testSAXParse() throws ParserConfigurationException, SAXException, IOException {
//定義一個(gè)factory API文兢,能夠配置和獲取一個(gè)SAX解析器去解析xml
//SAXParserFactory.newInstance();返回Android的接口SAXParserFactory,不像其他Java接口焕檬,該方法不能產(chǎn)生系統(tǒng)屬性
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();//屬性文件或服務(wù)API
//定義一個(gè)API包裹XMLReader實(shí)現(xiàn)類
SAXParser saxParser = saxParserFactory.newSAXParser();
//讀一個(gè)xml文檔的接口姆坚,用于回調(diào)
XMLReader xmlReader = saxParser.getXMLReader();
saxParseHandler = new SAXParseHandler();
//將saxParseHandler的實(shí)例設(shè)置到XMLReader中
xmlReader.setContentHandler(saxParseHandler);
InputStream inputStream = getResources().openRawResource(R.raw.test);
InputSource inputSource = new InputSource(inputStream);
//開始執(zhí)行解析
xmlReader.parse(inputSource);
}
以上代碼中的注釋寫的很詳細(xì),就不在啰嗦了实愚。
2.PULL
待補(bǔ)充...
三.解析Json
Android中解析Json的類有JSONObject和JSONArray兼呵。
格式化Json數(shù)據(jù)的網(wǎng)址:jsonlint.com
開源庫(kù):對(duì)開源庫(kù)還未進(jìn)行研究,待研究了回來補(bǔ)充...
- GSON
- fastJson
通過JSONObject和JSONArray來對(duì)下面一段Json數(shù)據(jù)進(jìn)行解析腊敲。
{city_info: [
{city: "南子島", cnty: "中國(guó)", id: "CN101310230", lat: "11.26", lon: "114.20", prov: "海南" },
{city: "北京", cnty: "中國(guó)", id: "CN101010100", lat: "39.904000", lon: "116.391000", prov: "直轄市" }, ...
] }
寫一個(gè)方法對(duì)以上Json數(shù)據(jù)進(jìn)行解析击喂,代碼如下:
public List<CityInfo> parseCityData(String cityData) {
List<CityInfo> cityInfos = new ArrayList<>();
try {
JSONObject jsonObject = new JSONObject(cityData);
JSONArray jsonArray = jsonObject.getJSONArray("city_info");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject cityObject = (JSONObject) jsonArray.get(i);
String city = cityObject.getString("city");
String prov = cityObject.getString("prov");
CityInfo cityInfo = new CityInfo(city, prov);
cityInfos.add(cityInfo);
}
} catch (JSONException e) {
e.printStackTrace();
}
return cityInfos;
}
通過new JSONObject()獲取整個(gè)JSONObject對(duì)象,然后利用getJSONArray()獲取city_info對(duì)應(yīng)的Json數(shù)組碰辅,然后再通過Json數(shù)組的get方法獲取數(shù)組中的每一個(gè)JSONObject對(duì)象懂昂,通過關(guān)鍵字獲取我們想要的數(shù)據(jù),最后將數(shù)據(jù)存入列表没宾。整個(gè)Json數(shù)據(jù)解析完畢凌彬。
四.網(wǎng)絡(luò)狀態(tài)處理
網(wǎng)絡(luò)狀態(tài)處理:可以判斷是否連接網(wǎng)絡(luò),還可以區(qū)分移動(dòng)網(wǎng)絡(luò)流量還是WiFi網(wǎng)絡(luò)流量
- ConnectivityManager
- NetworkInfo
五.擴(kuò)展
- 下載電影循衰、音樂的本質(zhì)铲敛?
網(wǎng)絡(luò)請(qǐng)求 - 斷點(diǎn)下載
記錄http的Head,下載時(shí)間会钝,下載了哪些東西原探。 - 常用網(wǎng)絡(luò)開源庫(kù)
- android-async-http
- volley
- OKHttp
- Retrofit
- 封裝請(qǐng)求及通用設(shè)置
- 封裝能用Header
- 請(qǐng)求參數(shù)封裝
- 封裝結(jié)果處理
- 能用錯(cuò)誤碼處理
- 數(shù)據(jù)轉(zhuǎn)換校驗(yàn)
- 攔截請(qǐng)求設(shè)置及代理
- Fiddler(Windows)
- Charles(Mac)
- wifi設(shè)置代理
- 技巧
- Postman查詢API
- Restful API