Android應(yīng)用開發(fā)基礎(chǔ)教程(微課版) 課件 第9、10章 網(wǎng)絡(luò)編程、高級應(yīng)用_第1頁
Android應(yīng)用開發(fā)基礎(chǔ)教程(微課版) 課件 第9、10章 網(wǎng)絡(luò)編程、高級應(yīng)用_第2頁
Android應(yīng)用開發(fā)基礎(chǔ)教程(微課版) 課件 第9、10章 網(wǎng)絡(luò)編程、高級應(yīng)用_第3頁
Android應(yīng)用開發(fā)基礎(chǔ)教程(微課版) 課件 第9、10章 網(wǎng)絡(luò)編程、高級應(yīng)用_第4頁
Android應(yīng)用開發(fā)基礎(chǔ)教程(微課版) 課件 第9、10章 網(wǎng)絡(luò)編程、高級應(yīng)用_第5頁
已閱讀5頁,還剩74頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

Andriod應(yīng)用開發(fā)基礎(chǔ)教程第9章網(wǎng)絡(luò)編程9.1UDP、TCP、HTTP協(xié)議基礎(chǔ)UDP是一種無連接的、不可靠的協(xié)議,它不會(huì)對數(shù)據(jù)進(jìn)行確認(rèn)或重傳,也不會(huì)進(jìn)行數(shù)據(jù)排序。UDP不需要建立連接,以報(bào)文(Datagram)為單位來收發(fā)數(shù)據(jù),數(shù)據(jù)包可以直接發(fā)送,每個(gè)UDP包都是獨(dú)立的,并且可能會(huì)在傳輸過程中丟失、重復(fù)、亂序。因此,UDP適用于需要快速傳輸數(shù)據(jù),而對數(shù)據(jù)可靠性要求不高的應(yīng)用場景,如網(wǎng)絡(luò)直播、在線游戲、IP電話、視頻會(huì)議等。TCP是一種面向連接的、可靠的協(xié)議,它為數(shù)據(jù)包的傳輸提供了確認(rèn)、重傳、數(shù)據(jù)排序和流量控制等功能,保證了數(shù)據(jù)的可靠性。TCP通過三次握手來建立連接,四次揮手來終止連接。在傳輸數(shù)據(jù)時(shí),TCP將數(shù)據(jù)分成多個(gè)包進(jìn)行傳輸,每個(gè)包都有自己的編號(hào)和校驗(yàn),接收方會(huì)對每個(gè)包進(jìn)行確認(rèn),如果某個(gè)包沒有被確認(rèn),發(fā)送方會(huì)重新發(fā)送這個(gè)包,直到接收方確認(rèn)為止。TCP適用于需要可靠傳輸?shù)膽?yīng)用場景,如文件傳輸、Web瀏覽器、電子郵件等。以人與人之間的通信為例,UDP協(xié)議就相當(dāng)于是寫信給對方,寄出去信件之后不能知道對方是否收到信件,信件內(nèi)容是否完整,也不能得到及時(shí)反饋,而TCP協(xié)議就像是打電話通信,在這一系列流程都能得到及時(shí)反饋,并能確保對方及時(shí)接收到。HTTP協(xié)議全稱為HypertextTransferProtocol,即超文本傳輸協(xié)議,是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)傳輸協(xié)議。HTTP協(xié)議定義了客戶端(Browser)與服務(wù)器之間的通信規(guī)范,以實(shí)現(xiàn)對各種資源(如HTML頁面、圖像、音頻、視頻等)的傳輸和訪問。HTTP協(xié)議是一個(gè)無狀態(tài)的應(yīng)用層協(xié)議,基于請求響應(yīng)模式且請求和響應(yīng)都是一條文本消息,再則HTTP協(xié)議是一個(gè)無連接協(xié)議,所以每個(gè)請求都是獨(dú)立的,服務(wù)器處理請求后立即關(guān)閉連接。9.2Socket通信Socket就是兩個(gè)應(yīng)用程序通過一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換,連接的一段就是一個(gè)Socket,又稱為套接字。實(shí)現(xiàn)一個(gè)Socket連接通信至少需要兩個(gè)套接字,一個(gè)運(yùn)行在服務(wù)端(插孔),一個(gè)運(yùn)行在客戶端(插頭)。套接字用于描述IP地址和端口,是一個(gè)通信鏈的句柄。應(yīng)用程序通過套接字向網(wǎng)絡(luò)發(fā)出請求或應(yīng)答網(wǎng)絡(luò)請求。注意的是套接字既不是程序也不是協(xié)議,只是操作系統(tǒng)提供給通信層的一組抽象API接口。Socket通信是指應(yīng)用程序利用Socket接口實(shí)現(xiàn)的網(wǎng)絡(luò)通信,用于在不同的計(jì)算機(jī)之間傳輸數(shù)據(jù)。Socket是一種標(biāo)準(zhǔn)的API(應(yīng)用程序接口),可用于在不同的計(jì)算機(jī)之間傳輸數(shù)據(jù),它支持TCP、UDP等多種網(wǎng)絡(luò)協(xié)議。在Socket通信中,客戶端和服務(wù)器通過Socket接口進(jìn)行通信,通信時(shí)需指定IP地址和端口號(hào),IP地址用于唯一標(biāo)志網(wǎng)絡(luò)設(shè)備,端口主要用于區(qū)分主機(jī)上的不同應(yīng)用(沒有端口,操作系統(tǒng)沒有辦法區(qū)分?jǐn)?shù)據(jù)到底應(yīng)該發(fā)送到哪一個(gè)應(yīng)用上。客戶端創(chuàng)建一個(gè)Socket對象,并將其連接到服務(wù)器上的一個(gè)特定端口號(hào),通過Socket對象向服務(wù)器發(fā)送數(shù)據(jù)。服務(wù)器監(jiān)聽指定端口號(hào),等待客戶端的連接請求,當(dāng)連接請求到達(dá)時(shí),服務(wù)器會(huì)創(chuàng)建一個(gè)新的Socket對象,并與客戶端的Socket對象建立連接。然后,服務(wù)器和客戶端之間就可以進(jìn)行數(shù)據(jù)傳輸了。Socket通信的優(yōu)點(diǎn)是它是跨平臺(tái)的,因?yàn)镾ocket接口是標(biāo)準(zhǔn)的API,不受特定操作系統(tǒng)的限制。它也很靈活,可以使用不同的網(wǎng)絡(luò)協(xié)議(如TCP和UDP),以滿足不同的需求。Socket通信廣泛應(yīng)用于客戶端-服務(wù)器應(yīng)用程序、分布式計(jì)算、實(shí)時(shí)數(shù)據(jù)傳輸?shù)阮I(lǐng)域。例如,Web服務(wù)器使用Socket通信與客戶端瀏覽器進(jìn)行通信,從而提供Web服務(wù)。9.2.1UDP類型

基于UDP協(xié)議的SocketAPI中,要分清楚DatagramSocket和DatagramPacket這兩個(gè)類。Datagram意為數(shù)據(jù)包,Packet意為包裹,這兩個(gè)類的關(guān)系相當(dāng)于DatagramPacket是發(fā)送接收的數(shù)據(jù)包包裹,DatagramSocket是發(fā)送接收數(shù)據(jù)包包裹的快遞員。表9-1(a)DatagramPacket類構(gòu)造方法構(gòu)造函數(shù)名稱說明DatagramPacket(byte[]buf,intlength)接收構(gòu)造函數(shù),用來接收長度為length的數(shù)據(jù)包DatagramPacket(byte[]buf,intlength,InetAddressaddress,intport)發(fā)送構(gòu)造函數(shù),構(gòu)造數(shù)據(jù)報(bào)包,用來將長度為

length的包發(fā)送到指定主機(jī)上的指定端口號(hào)包表9-1(b)DatagramPacket類成員方法成員方法說明InetAddressgetAddress()從接收或發(fā)送的數(shù)據(jù)報(bào)中獲取對端的IP地址intgetPort()intgetPort()

從接收或發(fā)送的數(shù)據(jù)報(bào)中獲取對端的端口號(hào)byte[]getData()獲取數(shù)據(jù)報(bào)中的數(shù)據(jù),數(shù)據(jù)存在字節(jié)數(shù)組中intgetLength()獲取數(shù)據(jù)報(bào)中的數(shù)據(jù)的實(shí)際長度InetAddressgetAddress()從接收或發(fā)送的數(shù)據(jù)報(bào)中獲取對端的IP地址DatagramPacket類表示數(shù)據(jù)報(bào)包,來實(shí)現(xiàn)無連接包投遞服務(wù)。每條報(bào)文僅根據(jù)該包中包含的信息從一臺(tái)機(jī)器路由到另一臺(tái)機(jī)器。從一臺(tái)機(jī)器發(fā)送到另一臺(tái)機(jī)器的多個(gè)包可能選擇不同的路由,也可能按不同的順序到達(dá),不保證包順利投遞。表9-2(a)DatagramSocket類構(gòu)造方法表9-2(b)DatagramSocket類成員和方法DatagramSocket類表示用來發(fā)送和接收數(shù)據(jù)報(bào)包的套接字。數(shù)據(jù)報(bào)套接字是包投遞服務(wù)的發(fā)送或接收點(diǎn)。每個(gè)在數(shù)據(jù)報(bào)套接字上發(fā)送或接收的包都是單獨(dú)編址和路由的。從一臺(tái)機(jī)器發(fā)送到另一臺(tái)機(jī)器的多個(gè)包可能選擇不同的路由,也可能按不同的順序到達(dá)。在DatagramSocket總是啟用UDP廣播發(fā)送。為了接收廣播包,應(yīng)該將DatagramSocket綁定到通配符地址。在某些實(shí)現(xiàn)中,將DatagramSocket綁定到一個(gè)更加具體的地址時(shí)廣播包也可以被接收。構(gòu)造函數(shù)名稱說明DatagramSocket(intport)創(chuàng)建一個(gè)UDPSocket對象,一般用于服務(wù)器,需要指定本機(jī)端口號(hào)(port)DatagramSocket()創(chuàng)建一個(gè)UDPSocket對象,一般用于客戶端,不需要指定本機(jī)端口號(hào),由操作系統(tǒng)隨機(jī)分配構(gòu)造函數(shù)名稱說明void

receive(DatagramPacketp)接收數(shù)據(jù)報(bào),如果沒接收到,阻塞等待void

send(DatagramPacketp)發(fā)送數(shù)據(jù)報(bào),不會(huì)阻塞等待void

close()關(guān)閉套接字案例9.1

通過UDP實(shí)現(xiàn)網(wǎng)絡(luò)通信。(參考代碼見:web模塊下com.example.web.udp包中)依次運(yùn)行Udpserver和Udpclient,UDP客戶端發(fā)送信息“我是客戶端”,UDP服務(wù)端輸出的信息如圖9-3(a)所示,UDP服務(wù)端發(fā)送信息“服務(wù)端在此”,UDP客戶端輸出的信息如圖9-3(b)所示,UDP客戶端和服務(wù)端實(shí)現(xiàn)相互通信。圖9-3(a)UDP服務(wù)端輸出信息圖9-3(b)UDP客戶端輸出信息9.2.2TCP類型

基于TCP協(xié)議的SocketAPI中,ServerSocket和Socket這兩個(gè)類尤為重要。其中類ServerSocket實(shí)現(xiàn)服務(wù)器套接字,該類遵循TCP協(xié)議,所以必須要和客戶端Socket建立連接才能完成信息的接送,服務(wù)器套接字等待來自網(wǎng)絡(luò)的請求,它基于該請求執(zhí)行某些操作,請求成功則向請求者返回結(jié)果。Socket類現(xiàn)了客戶端套接字,套接字是兩臺(tái)機(jī)器間通信的端點(diǎn),該類同樣遵循TCP協(xié)議,所以必須與ServerSocket建立連接后,才能進(jìn)行信息的傳送。表9-3(a)ServerSocket類成員方法表9-3(b)Socket類成員方法類名稱用途Socketaccept()偵聽并接收到此套接字的連接voidbind(SocketAddressendpoint,intbacklog)將ServerSocket綁定到特定地址(IP地址和端口號(hào))InetAddressgetInetAddress()返回此服務(wù)器套接字的本地地址intgetLocalPort()返回此套接字正在偵聽的端口號(hào)SocketAddressgetLocalSocketAddress()返回此套接字綁定到的端點(diǎn)的地址voidclose()關(guān)閉這個(gè)套接字類名稱用途voidbind(SocketAddressbindpoint)將套接字綁定到本地地址InetAddressgetLocalAddress()獲取綁定的套接字的本地地址InetAddressgetInetAddress()返回套接字連接的地址intgetLocalPort()返回此套接字綁定的本地端口號(hào)intgetPort()返回此套接字連接的遠(yuǎn)程端口號(hào)OutputStreamgetOutputStream()返回此套接字的輸出流InputStreamgetInputStream()返回此套接字的輸入流voidshutdownInput()將此套接字的輸入流放在“流結(jié)束”中voidshutdownOutput()禁用此套接字的輸出流voidclose()關(guān)閉此套接字表9-4基于TCP協(xié)議的Socket通信用到的其它類類名稱用途InputStream、OutputStream處理字節(jié)流的抽象類,字節(jié)流的所有類的超類InputStreamReader、OutputStreamWriter處理字符流的抽象類,字節(jié)流與字符流轉(zhuǎn)換的橋梁BufferedReader、BufferedWriterBufferedReader:由Reader類擴(kuò)展而來,提供通用的緩沖方式文本讀取,readLine讀取一個(gè)文本行,從字符輸入流中讀取文本,緩沖各個(gè)字符,從而提供字符、數(shù)組和行的高效讀取。BufferedWriter:由Writer類擴(kuò)展而來,提供通用的緩沖方式文本寫入,newLine使用平臺(tái)自己的行分隔符,將文本寫入字符輸出流,緩沖各個(gè)字符,且可以設(shè)置緩沖大小,從而提供單個(gè)字符、數(shù)組和字符串的高效寫入PrintWriter提供println()方法可以寫不同平臺(tái)的換行符通過TCP協(xié)議的Socket服務(wù)端和客戶端通信模型如圖9-4所示,實(shí)現(xiàn)步驟如下:(1)服務(wù)端創(chuàng)建ServerSocket;(2)服務(wù)端通過調(diào)用accept()方法開啟監(jiān)聽,等待接收客戶端請求;客戶端創(chuàng)建鏈接Socket向服務(wù)端發(fā)送請求;(3)服務(wù)端接收到來自于客戶端的請求后,創(chuàng)建鏈接Socket;(4)客戶端和服務(wù)端通過輸入輸出流實(shí)現(xiàn)數(shù)據(jù)交互,客戶端和服務(wù)端通信結(jié)束后,調(diào)用close()方法關(guān)閉Socket與相關(guān)資源。圖9-4Socket服務(wù)端和客戶端通信模型(通過TCP協(xié)議)在Socket通信過程中服務(wù)端執(zhí)行步驟為:(1)創(chuàng)建ServerSocket對象,綁定監(jiān)聽的端口;(2)調(diào)用accept()方法監(jiān)聽客戶端的請求;(3)連接建立后,通過輸入流讀取客戶端發(fā)送的請求信息;(4)通過輸出流向客戶端發(fā)送響應(yīng)信息;(5)關(guān)閉相關(guān)資源??蛻舳藞?zhí)行步驟為:(1)創(chuàng)建Socket對象,指明需要鏈接的服務(wù)器的地址和端號(hào);(2)鏈接建立后,通過輸出流向服務(wù)器發(fā)送請求信息;(3)通過輸入流獲取服務(wù)器響應(yīng)的信息;(4)關(guān)閉相關(guān)資源。案例9.2

通過TCP實(shí)現(xiàn)網(wǎng)絡(luò)通信(參考代碼見:web模塊下com.example.web.tcp包中)依次運(yùn)行TcpServer和TcpClient,TCP客戶端發(fā)送信息“我是客戶端”,TCP服務(wù)端輸出的信息如圖9-5(a)所示,TCP服務(wù)端發(fā)送信息“我是服務(wù)端”,TCP客戶端輸出的信息如圖9-5(b)所示,TCP客戶端和服務(wù)端實(shí)現(xiàn)相互通信。圖9-5(a)TCP服務(wù)端輸出的信息圖9-5(b)TCP客戶端輸出的信息9.3HTTP通信在瀏覽器的地址欄里輸入的網(wǎng)站地址叫做URL(UniformResourceLocator,統(tǒng)一資源定位符),每個(gè)網(wǎng)頁也都有一個(gè)Internet地址。當(dāng)我們在瀏覽器的地址框中輸入一個(gè)URL或是單擊一個(gè)超級鏈接時(shí),URL就確定了要瀏覽的地址。瀏覽器通過超文本傳輸協(xié)議(HTTP),將Web服務(wù)器上站點(diǎn)的網(wǎng)頁代碼提取出來進(jìn)行顯示。URL的組成為:協(xié)議名://域名:端口/路徑/文件名,例如:8080/zhangsan/index.html,含義如下:(1)http://:代表超文本傳輸協(xié)議,通知服務(wù)器顯示W(wǎng)eb頁;(2)www:代表一個(gè)Web(萬維網(wǎng))服務(wù)器;(3):8080/:這是裝有網(wǎng)頁的服務(wù)器的域名(或站點(diǎn)服務(wù)器的名稱)和端口;(4)zhangsan/:為該服務(wù)器上的子目錄;(5)index.html:是文件夾中的一個(gè)HTML文件。9.3.1HTTP請求消息

用戶在瀏覽器中訪問URL或是單擊一個(gè)超級鏈接時(shí),瀏覽器會(huì)向服務(wù)器發(fā)送HTTP請求,瀏覽器發(fā)送到服務(wù)器的消息叫做HTTP請求消息(又叫HTTP請求報(bào)文),請求消息由請求行、請求頭部、空行和請求體四部分組成請求行由請求方式、URL和HTTP協(xié)議版本3個(gè)部分組成。請求頭部用來描述客戶端的基本信息,從而把客戶端相關(guān)的信息告知服務(wù)器。請求頭部由多個(gè)鍵值對組成,常見的請求頭字段如表9-5所示。最后一個(gè)請求頭字段后面是一個(gè)空行,用來分割請求頭部和請求體,不過一些瀏覽器調(diào)試工具中經(jīng)過美化后這個(gè)空行沒有顯示出來,可以看作用一條橫線代替。請求體中存放的,是要通過POST方式提交到服務(wù)器的數(shù)據(jù),由于GET請求是從服務(wù)器獲取數(shù)據(jù),所以GET請求沒有請求體。表9-5常見的請求頭字段頭部字段說明Host指定資源所在的服務(wù)器主機(jī)名和端口號(hào)Connection客戶端與服務(wù)器之間的連接狀態(tài)Content-Length請求體大小Content-Type客戶端告知服務(wù)器實(shí)際發(fā)送的數(shù)據(jù)類型Accept客戶端可識(shí)別的響應(yīng)內(nèi)容MIME類型列表Accept-Encoding客戶端能進(jìn)行解碼的的數(shù)據(jù)解碼方式Accept-Language客戶端期望服務(wù)器返回那個(gè)國家語言的文檔User-Agent即用戶代理,指定客戶端客戶端使用的操作系統(tǒng)及版本、瀏覽器及版本、瀏覽語言等,使得服務(wù)器針對不同類型的瀏覽器返回不同內(nèi)容9.3.2響應(yīng)消息

服務(wù)器接收到請求消息后,會(huì)將處理后的數(shù)據(jù)交給客戶端,及HTTP響應(yīng)消息,響應(yīng)消息由狀態(tài)行、響應(yīng)頭部、空行和響應(yīng)體4個(gè)部分組成。狀態(tài)行位于響應(yīng)消息的第一行,由HTTP協(xié)議版本、狀態(tài)碼、狀態(tài)碼的描述文本3個(gè)部分組成,客戶端可根據(jù)服務(wù)器返回的響應(yīng)狀態(tài)碼得知此次HTTP請求的結(jié)果時(shí)否成功,也可以根據(jù)狀態(tài)碼的類型分析除此次請求不成功的錯(cuò)誤原因,狀態(tài)碼第一位數(shù)字有5種取值。表9-6狀態(tài)碼取值及描述信息狀態(tài)碼取值描述1xx信息,服務(wù)器收到請求,需要請求者繼續(xù)執(zhí)行操作2xx成功,請求成功被服務(wù)器接收并處理3xx重定向,需要進(jìn)一步的操作以完成請求4xx客戶端請求錯(cuò)誤5xx服務(wù)器錯(cuò)誤,服務(wù)器在處理請求的過程中發(fā)生錯(cuò)誤響應(yīng)頭部用來描述服務(wù)器的基本信息,響應(yīng)頭部由多個(gè)鍵值對組成,常用的響應(yīng)頭字段及其描述如表9-7所示,更多的響應(yīng)頭字段的描述,可以查看MDN官方文檔:/zh-CN/docs/Web/HTTP/Headers。響應(yīng)體中存放的,是服務(wù)器響應(yīng)給客戶端的資源內(nèi)容,可以通過瀏覽器調(diào)試工具中的Response面板查看服務(wù)器響應(yīng)回來的內(nèi)容,響應(yīng)體可以包含各種類型的數(shù)據(jù),如HTML文檔、JSON數(shù)據(jù)、文件等。表9-7常用的響應(yīng)頭字段和說明頭部字段說明Age對象在緩存代理中存貯的時(shí)長,以秒為單位Location需要將頁面重新定向至的地址,為一個(gè)使用絕對路徑的地址,一般在響應(yīng)碼為3xx的響應(yīng)中才會(huì)有意義Server處理請求的源頭服務(wù)器所用到的軟件相關(guān)信息Accept-Ranges服務(wù)器使用HTTP響應(yīng)頭Accept-Ranges標(biāo)識(shí)自身支持范圍請求,單位值為bytes或者noneContent-Disposition在常規(guī)的HTTP應(yīng)答中,Content-Disposition響應(yīng)標(biāo)頭指示回復(fù)的內(nèi)容該以何種形式展示,是以內(nèi)聯(lián)的形式(即網(wǎng)頁或者頁面的一部分),還是以附件的形式下載并保存到本地。Vary描述了除方法和URL之外影響響應(yīng)內(nèi)容的請求頭字段名。9.3.3HTTP通信

HTTP實(shí)際上是基于TCP的應(yīng)用層協(xié)議,它在更高的層次封裝了TCP的使用細(xì)節(jié),使網(wǎng)絡(luò)請求操作更為易用。TCP連接是因特網(wǎng)上基于流的可靠連接,它為HTTP提供了一條可靠的比特傳輸管道,從TCP連接一端填入的字節(jié)會(huì)從另一端以原有的順序,正確地傳遞出來。表9-8HttpURLConnection類成員方法及說明方法名說明intgetResponseCode()從HTTP響應(yīng)消息獲取狀態(tài)碼voidsetRequestMethod(Stringmethod)設(shè)置發(fā)送請求的方法StringgetRequestMethod()獲取發(fā)送請求的方法voidsetRequestProperty(Stringkey,Stringvalue)設(shè)置HTTP請求的請求頭StringgetResponseMessage()獲取服務(wù)器的響應(yīng)消息(如果有)HttpURLConnection這個(gè)類位于包中,是Java的標(biāo)準(zhǔn)類,對外提供訪問HTTP協(xié)議的基本功能,繼承自URLConnection,可用于向網(wǎng)站發(fā)送GET和POST請求。案例9.3

通過HTTP實(shí)現(xiàn)網(wǎng)絡(luò)通信訪問豆瓣電影首頁:/并返回網(wǎng)頁源代碼。(參考代碼見:web模塊下com.example.web.http包中)網(wǎng)頁源代碼即一個(gè)網(wǎng)站的原始代碼,這些代碼是用HTML(超文本標(biāo)記語言)編寫的,源代碼是未編譯的文本代碼,可以通過瀏覽器或服務(wù)器翻譯成網(wǎng)站最終顯示的內(nèi)容,瀏覽器和服務(wù)器對這些代碼進(jìn)行解釋和渲染,從而在網(wǎng)頁上顯示我們看見的內(nèi)容,那么怎么從網(wǎng)頁源代碼提取我們想要的有用信息呢?對網(wǎng)頁源代碼解析的工具這里選擇Jsoup。Jsoup可從從Jsoup官網(wǎng):/download下載對應(yīng)的jar包,并將該文件放入項(xiàng)目的libs文件夾內(nèi),如下圖所示。同時(shí)在項(xiàng)目的build.gradle文件中添加:implementation'org.jsoup:jsoup:1.17.2',“1.17.2”是jsoup的版本號(hào),要根據(jù)實(shí)際下載的版本號(hào)對該值進(jìn)行修改,然后運(yùn)行build.gradle文件,使得jsoup在整個(gè)項(xiàng)目中可以調(diào)用。Jsoup爬蟲工具使用步驟如下:(1)通過URL獲得Doucment對象;(2)調(diào)用select()方法從Document實(shí)例中篩選Elements元素;(3)調(diào)用text()方法將Element(s)對象轉(zhuǎn)化為String類型從而獲得想要的內(nèi)容表9-9Selector選擇器基本語法語法示例示例說明tagnamep選擇標(biāo)簽名為p的元素.class.showtxt選擇class=’showtxt’的所有元素#id#name選擇id=’name’的所有元素[attribute][target]選擇帶有target屬性的所有元素[attr=value][target=blank]選擇target="blank"的所有元素[attr^=value][src^="https"]選擇src屬性值以“https”開頭的所有元素[attr$=value][src$=".pdf"]選擇其src屬性值以“.pdf”結(jié)尾的所有元素parent>childdiv>p選擇父元素標(biāo)簽名為div的所有標(biāo)簽名為p的元素ancestorchilddivp選擇父輩元素標(biāo)簽名為div的內(nèi)部標(biāo)簽名為p的元素9.4網(wǎng)絡(luò)編程綜合案例案例9.4

通過HTTP通信訪問筆趣看網(wǎng)頁,在模擬器應(yīng)用上輸入小說代號(hào)和章節(jié)代號(hào)后將對應(yīng)的小說章節(jié)內(nèi)容顯示到模擬器應(yīng)用頁面上。(參考代碼見:web模塊下com.example.web和com.example.web.novel包中)Andriod應(yīng)用開發(fā)基礎(chǔ)教程第10章高級應(yīng)用10.1動(dòng)畫動(dòng)畫除了添加視覺提示,通知用戶應(yīng)用中的動(dòng)態(tài),還能讓應(yīng)用更精美,使其擁有更優(yōu)質(zhì)的外觀和風(fēng)格。Android包含不同的動(dòng)畫API,具體取決于動(dòng)畫類型。下面簡單地介紹一下向界面添加動(dòng)畫的不同方法。10.1.1逐幀動(dòng)畫

在Android應(yīng)用開發(fā)中,逐幀動(dòng)畫是一種常見的動(dòng)畫效果,它通過顯示一系列連續(xù)的圖像來創(chuàng)建動(dòng)畫效果。實(shí)現(xiàn)步驟如下:(1)準(zhǔn)備逐幀動(dòng)畫所需的圖像資源;(2)在布局文件中添加ImageView組件用于顯示動(dòng)畫;(3)創(chuàng)建AnimationDrawable對象用于管理逐幀動(dòng)畫;(4)將幀圖像資源添加到AnimationDrawable對象;(5)將AnimationDrawable對象設(shè)置為ImageView的背景;啟動(dòng)動(dòng)畫。案例10.1

演示逐幀動(dòng)畫.(參考代碼見:FrameActivity)點(diǎn)擊界面“start”按鈕,將循環(huán)播放動(dòng)畫,每張圖片延遲1秒播放下一張圖片,點(diǎn)擊“stop”按鈕動(dòng)畫將停止播放。10.1.2視圖動(dòng)畫

在Android開發(fā)中,View動(dòng)畫是一種常見的動(dòng)畫效果,View動(dòng)畫的作用對象是View,支持4種動(dòng)畫效果,分別是平移動(dòng)畫、縮放動(dòng)畫、透明度動(dòng)畫和旋轉(zhuǎn)動(dòng)畫。這四種變換效果對應(yīng)著Animation的四個(gè)子類:TranslateAnimation、ScaleAnimation、AlphaAnimation和RotateAnimation,這四種動(dòng)畫既可以通過XML來定義,也可以通過代碼來動(dòng)態(tài)創(chuàng)建。表10-1View動(dòng)畫4種變化說明動(dòng)畫名稱XML標(biāo)簽Animation子類效果平移動(dòng)畫<translate>TranslateAnimation平移View縮放動(dòng)畫<scale>ScaleAnimation縮放View旋轉(zhuǎn)動(dòng)畫<rotate>RotateAnimation旋轉(zhuǎn)動(dòng)畫透明度動(dòng)畫<alpha>AlphaAnimation改變View透明度案例10.2

通過XML來定義View動(dòng)畫并進(jìn)行演示(參考代碼見:animation模塊下anim資源目錄和com.example.animation.view包中)分別點(diǎn)擊應(yīng)用界面的Alpha、Scale、Translate、Rotate和Set將會(huì)產(chǎn)生對應(yīng)的透明度視圖動(dòng)畫、縮放視圖動(dòng)畫、平移視圖動(dòng)畫和集合視圖動(dòng)畫效果,點(diǎn)擊“點(diǎn)擊顯示重置按鈕”后,應(yīng)用上方將顯示重置按鈕,點(diǎn)擊重置按鈕視圖還原,可多次觀看視圖動(dòng)畫效果。案例10.3

通過Java定義View動(dòng)畫并進(jìn)行演示。(參考代碼見:animation模塊下acom.example.animation.view包中ViewJavaActivity)相對于案例10-2,不需要在anim目錄下創(chuàng)建XML文件,只需要通過Java代碼定義動(dòng)畫效果即可。布局文件和案例10-2相同,Activity代碼修改onClick()函數(shù)即可10.1.3

屬性動(dòng)畫

視圖動(dòng)畫只能對View對象添加動(dòng)畫效果,且只能對公開對象添加效果,比如實(shí)現(xiàn)對View的旋轉(zhuǎn)和平移,但是不能操作背景顏色。此外,視圖動(dòng)畫也不能修改實(shí)際的View的屬性和位置,只會(huì)使繪制View的屬性和位置發(fā)生變化,比如平移動(dòng)畫只會(huì)讓View在屏幕上移動(dòng),視覺效果上發(fā)生了平移,但是View的實(shí)際位置并不會(huì)更改。屬性動(dòng)畫幾乎可以為任何對象(視圖和非視圖)添加視圖效果,將對象屬性在指定的時(shí)間內(nèi)從初始值變?yōu)榱硪粋€(gè)值,改變的是對象本身。總的來說,屬性動(dòng)畫比視圖動(dòng)畫更加強(qiáng)大,具有更廣泛的應(yīng)用范圍。表10-2屬性動(dòng)畫相關(guān)類類名說明ValueAnimator屬性動(dòng)畫最為核心的類,處理動(dòng)畫邏輯ObjectAnimator對象屬性動(dòng)畫的操作類,使用該類能操作對象的屬性動(dòng)畫TimeInterpolator時(shí)間插值器,計(jì)算當(dāng)前屬性值改變的快慢,系統(tǒng)預(yù)置的有線性插值器、加速減速插值器、減速插值器Property屬性對象,主要定義了屬性的set和get方法PropertyValuesHolder持有目標(biāo)屬性Property、setter和getter方法、以及關(guān)鍵幀集合的類KeyframeSet存儲(chǔ)一個(gè)動(dòng)畫的關(guān)鍵幀集案例10.4屬性動(dòng)畫演示。(參考代碼見:animation模塊下PropertyActivity)不同于視圖動(dòng)畫的View,屬性動(dòng)畫中View的屬性發(fā)生了變化。10.2

多媒體表10-3MediaPlayer類常用方法方法名說明SetDataSource(Stringpath)設(shè)置音視頻源getCurrentPosition()獲取當(dāng)前播放位置getDuration()獲取載入音視頻總長getVideoHeight()獲取視頻高度getVideoWidth獲取視頻寬度isPlaying()當(dāng)前是否正在播放prepare()音視頻播放之前,調(diào)用完成MediaPlayer同步播放準(zhǔn)備工作prepareAsync()音視頻播放之前,調(diào)用完成MediaPlayer異步播放準(zhǔn)備工作setVolume(floatleftVolume,floatrightVolume)設(shè)置播放器音量上下限SetDisplay(SurfaceHoldersh)SetOnCompletionListener(MediaPlayer.OnCompletionListenerlistenser)顯示媒體的視頻部分圖像設(shè)置音視頻播放結(jié)束之后的監(jiān)聽事件SeekTo(int32position)到達(dá)音視頻指定的時(shí)間位置SetOnErrorListener(MediaPlayer.OnErrorListenerlistenser)設(shè)置音視頻播放錯(cuò)誤時(shí)的監(jiān)聽事件SetOnPreparedListener(MediaPlayer.OnPreparedListenerlistenser)設(shè)置音視頻播放錯(cuò)誤時(shí)的監(jiān)聽事件SetOnSeekCompleteListener((MediaPlayer.OnSeekCompleteListenerlistenser))設(shè)置定位完成時(shí)的監(jiān)聽事件start()開始播放stop()停止播放pause()暫停播放reset()重置播放release()釋放資源在Android應(yīng)用程序中播放音視頻是一項(xiàng)常見的需求,AndroidStudio提供了MediaPlayer類,可以很方便地實(shí)現(xiàn)音視頻播放功能但MediaPlayer沒有提供圖像輸出界面,需要借助SurfaceView來顯示MediaPlayer播放的圖像,可用SurfaceHolder的回調(diào)方法繪制SurfaceView的內(nèi)容,控制圖形的尺寸和大小。而Surface是Android的一個(gè)重要元素,用于Android畫面的圖形繪制,每一個(gè)SurfaceView都內(nèi)嵌封裝一個(gè)Surface。表10-4SurfaceHolder的回調(diào)方法方法名說明surfaceCreated(SurfaceHolderholder)Surface第一次創(chuàng)建后立即被調(diào)用surfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight)Surface發(fā)生變化的時(shí)候被調(diào)用surfaceDestroyed(@NonNullSurfaceHolderholder)Surface被摧毀前被調(diào)用實(shí)現(xiàn)音頻播放步驟如下:(1)初始化MediaPlayer;(2)設(shè)置音頻文件的數(shù)據(jù)源;(3)準(zhǔn)備和播放;(4)監(jiān)聽播放事件;(5)釋放資源。案例10.5

實(shí)現(xiàn)視頻資源的播放(參考代碼見:media模塊下)應(yīng)用界面顯示視頻播放時(shí)長和播放進(jìn)度,滑動(dòng)進(jìn)度條視頻可從滑動(dòng)進(jìn)度條停止位置開始播放,單擊“后退”按鈕,視頻倒放5s,單擊“暫?!?,視頻停止播放,單擊“開始”按鈕,視頻開始播放,單擊“前進(jìn)”按鈕,視頻倒放5s。10.3

AsyncTask異步任務(wù)10.3.1線程

線程(Thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,多線程即一個(gè)進(jìn)程中并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù),多個(gè)線程可以更好地利用CPU的處理能力,提高程序的執(zhí)行效率。當(dāng)一個(gè)程序第一次啟動(dòng)的時(shí)候,Android會(huì)啟動(dòng)一個(gè)主線程即UI線程,主要負(fù)責(zé)處理用戶和界面相關(guān)的事件,如按鍵事件、觸屏事件等,并把相關(guān)的事件分發(fā)到對應(yīng)的組件進(jìn)行處理,如果其它相對耗時(shí)的操作阻塞UI線程,UI線程可能會(huì)失去響應(yīng),導(dǎo)致用戶界面卡頓產(chǎn)生NR(ApplicationNotResponding),俗稱死機(jī),因而常將耗時(shí)操作放在新線程中。Java線程開發(fā)中常使用的方法主要有以下三種:(1)新建一個(gè)java類,使其繼承Thread類,在Activity中調(diào)用該類即可;(2)匿名Thread類,使用Runnable接口;(3)實(shí)現(xiàn)Runnable接口,在Activity中調(diào)用。10.3.2AsyncTask及使用

新線程可能需要與主線程通信如動(dòng)態(tài)更新UI組件,但是新線程不允許直接更新UI組件,為了解決這個(gè)問題,Android提供了異步任務(wù)(AsyncTask)的方式實(shí)現(xiàn)異步線程的操作。AsyncTask實(shí)質(zhì)上是對JavaSE庫中Thread的一個(gè)封裝,加上了Android平臺(tái)自己的特性,它是Android1.5加入的用于實(shí)現(xiàn)異步操作的一個(gè)類,讓Android平臺(tái)上異步操作更加的安全,方便和實(shí)用。由于Thread只有一個(gè)run()方法,一旦開始,無法停止,與主線程通信較為繁瑣,它適合于一個(gè)非常獨(dú)立的異步任務(wù),因而獨(dú)立任務(wù)時(shí)可用Thread,其他時(shí)候盡可能用AsyncTask實(shí)現(xiàn)異步任務(wù)。AsyncTask異步實(shí)現(xiàn)方法步驟如下:(1)創(chuàng)建AsyncTask的子類,并指定參數(shù)類型;(2)實(shí)現(xiàn)AsyncTask方法,AsyncTask類常見的回調(diào)方法如表10-5所示;(3)通過AsyncTask子類的實(shí)例調(diào)用execute()方法執(zhí)行耗時(shí)操作,注意實(shí)例只能執(zhí)行execute()方法一次,否則會(huì)拋出異常。表10-5AsyncTask類常見的回調(diào)方法方法說明voidonPreExecute()線程任務(wù)開始前執(zhí)行voidonPostExecute(Booleanresult)線程任務(wù)結(jié)束時(shí)執(zhí)行BooleandoInBackground(String...params)在后臺(tái)執(zhí)行的線程任務(wù)時(shí)自動(dòng)調(diào)用voidonProgressUpdate(Integer...values)任務(wù)處理過程中進(jìn)度處理,調(diào)用publishProgress()時(shí)自動(dòng)調(diào)用execute(Params

params)觸發(fā)異步線程任務(wù)案例10.6

使用AsyncTask實(shí)現(xiàn)從網(wǎng)絡(luò)上異步下載文件并且將文件保存在外部存儲(chǔ)中,在文件的下載過程中顯示下載進(jìn)度。(參考代碼見:asynctask模塊下)10.4

Handler10.4.1Handler概念和相關(guān)機(jī)制

Handler是一套Android消息傳遞機(jī)制,主要用于線程間通信,Handler運(yùn)行在主線程中,子線程中需更新UI的操作信息可以通過Message對象傳遞到UI主線程,從而實(shí)現(xiàn)子線程對UI的更新處理,最終實(shí)現(xiàn)對異步消息的處理,保證線程安全??梢钥闯鯤andle主要具備兩個(gè)功能,一個(gè)是更新UI,另一個(gè)就是發(fā)送消息和對消息進(jìn)行處理。Handle消息傳遞機(jī)制流程主要包括4個(gè)步驟:異步通信準(zhǔn)備、消息發(fā)送、消息循環(huán)和消息處理Handler發(fā)送一個(gè)消息后,會(huì)將此消息加入消息隊(duì)列中,循環(huán)器遍歷消息隊(duì)列并且將隊(duì)列中的消息分發(fā)給對應(yīng)的Handler進(jìn)行處理,這就完成了一個(gè)消息的發(fā)送和處理過程。表10-6Handle消息傳遞機(jī)制各自角色和作用概念作用UI線程處理與UI相關(guān)的更新、操作等事件子線程人為開啟的線程,處理耗時(shí)操作消息線程間通訊的數(shù)據(jù)單元,存儲(chǔ)需操作的通信消息消息隊(duì)列存儲(chǔ)Handler發(fā)送過來的消息(Message)Handler添加消息到消息隊(duì)列;處理循環(huán)器分派過來的消息Looper消息循環(huán):循環(huán)取出消息隊(duì)列的消息和將取出的消息發(fā)送給對應(yīng)的Handler處理表10-7Handle機(jī)制中的核心類類名稱重要方法作用處理器類HandlersendMessage(Messagemsg)將消息發(fā)送到隊(duì)列中post(Runnabler)dispatchMessage(Messagemsg)將消息發(fā)送給對應(yīng)的HandlerhandleMessage(Messagemsg)對消息進(jìn)行相關(guān)處理消息隊(duì)列類MessageenqueueMessage(Messagemsg,longwhen)入隊(duì):將消息插入到消息隊(duì)列中Messagenext()出列:從消息隊(duì)列中移出消息循環(huán)器類Looperprepare()初始化循環(huán)器,創(chuàng)建消息隊(duì)列l(wèi)oop()消息循環(huán)Handler使用步驟分為四步:(1)新建Handler對象,覆寫handleMessage(Messagemsg)方法;(2)新建Message對象,設(shè)置其攜帶的數(shù)據(jù);(3)在子線程中通過Handler.sendMessage(Messagemsg)等方法發(fā)送信息;在Handler的handleMessage(Messagemsg)方法中處理消息,通知主線程作出相對應(yīng)的UI工作。Message類是一個(gè)包含任意類型的描述數(shù)據(jù)對象,此對象可以發(fā)送給Handler。對象包含兩個(gè)額外的int字段和一個(gè)額外的對象字段,這樣可以使得在很多情況下不用做分配工作。盡管Message的構(gòu)造器是公開的,但是獲取Message對象的最好方法是調(diào)用Message.obtain()或者Handler.obtainMessage(),這樣是從一個(gè)可回收對象池中獲取Message對象。表10-8Message類字段及含義字段含義what用戶自定義的消息代碼,這樣接收者可以識(shí)別這個(gè)消息的信息來源。每個(gè)Handler包含自己的消息代碼,所以不用擔(dān)心自定義的消息跟其他Handlers有沖突。arg1定義傳遞的int類型的值1arg2定義傳遞的int類型的值2obj定義傳遞的值類型是object(對象),可以傳遞各種類型的值10.4.2Handler應(yīng)用

案例10.7

通過Handler實(shí)現(xiàn)倒計(jì)時(shí)操作。(參考代碼見:handle模塊下)用戶可以選擇倒計(jì)時(shí)結(jié)束的日期和時(shí)間,點(diǎn)擊“點(diǎn)擊進(jìn)入倒計(jì)時(shí)”按鈕,如果倒計(jì)時(shí)日期和時(shí)間比當(dāng)前時(shí)間早,不會(huì)進(jìn)入倒計(jì)時(shí)操作,當(dāng)?shù)褂?jì)時(shí)日期和時(shí)間比當(dāng)前時(shí)間晚,倒計(jì)時(shí)開始。10.5

Fragment10.5.1Fragment概述

Fragment是Android3.0引入的新API,它可以看作是Activity中的子頁面,能單獨(dú)進(jìn)行管理和維護(hù),一個(gè)Fragment可以被多個(gè)Activity或者其他Fragment使用,也可以嵌套其他的Fragment,提高應(yīng)用程序的代碼可重用性和靈活性,F(xiàn)ragment也可以在運(yùn)行時(shí)動(dòng)態(tài)地添加、移除、替換等UI元素,提供更加靈活的響應(yīng)式用戶界面,但它不能單獨(dú)使用必須被“嵌入”到Activity中。Fragment可以靈活地適應(yīng)不同的屏幕尺寸和設(shè)備類型,使得應(yīng)用程序在各種設(shè)備上都能夠自適應(yīng),下圖展示了Fragment分別對應(yīng)手機(jī)與平板間不同情況的處理。平板屏幕尺寸較大一個(gè)Activity同時(shí)包含兩個(gè)Fragment,即左側(cè)的FragmentA導(dǎo)航欄和右側(cè)的FragmentB內(nèi)容列表,選擇Activity中的FragmentA導(dǎo)航欄項(xiàng)能跳轉(zhuǎn)到同一個(gè)Activity中的FragmentB內(nèi)容列表,手機(jī)由于屏幕尺寸較小一個(gè)Activity只包含一個(gè)Fragment,選擇一個(gè)Activity中的FragmentA導(dǎo)航欄項(xiàng)會(huì)跳轉(zhuǎn)到另一個(gè)Activity中的FragmentB內(nèi)容列表。10.5.2Fragment生命周期

Fragment擁有自己的生命周期,但是還是會(huì)受到Activity的生命周期的影響,只有Activity處于運(yùn)行狀態(tài)才可以對Fragment操作,也就是說Activity銷毀時(shí),Activity中所有的Fragment都會(huì)銷毀。表10-9Fragment生命周期方法生命周期含義onAttach()Fragment被添加到Activity時(shí)被回調(diào)onCreate()創(chuàng)建Fragment時(shí)被回調(diào)onCreateView()每次創(chuàng)建、繪制該Fragment的View組件時(shí)回調(diào)該方法onActivityCreated()Fragment所在的Activity被啟動(dòng)完成后回調(diào)該方法onStart()啟動(dòng)Fragment時(shí)被回調(diào)onResume()恢復(fù)Fragment時(shí)被回調(diào),F(xiàn)ragment能與用戶交互onPause()暫停Fragment時(shí)被回調(diào),F(xiàn)ragment不再與用戶交互onStop()停止Fragment時(shí)被回調(diào),F(xiàn)ragment不可見時(shí)回調(diào)onDestroyView()銷毀與Fragment有關(guān)的視圖,但未與Activity解除綁定onDestroy()銷毀Fragment時(shí)被回調(diào)onDetach()Fragment與Activity關(guān)聯(lián)被取消時(shí)調(diào)用10

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論