![基于Vitamio的安卓端手機(jī)播放器設(shè)計(jì)和實(shí)現(xiàn)計(jì)算機(jī)專業(yè)_第1頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/8/5908c390-3c16-4c45-9f4b-0979fb28023a/5908c390-3c16-4c45-9f4b-0979fb28023a1.gif)
![基于Vitamio的安卓端手機(jī)播放器設(shè)計(jì)和實(shí)現(xiàn)計(jì)算機(jī)專業(yè)_第2頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/8/5908c390-3c16-4c45-9f4b-0979fb28023a/5908c390-3c16-4c45-9f4b-0979fb28023a2.gif)
![基于Vitamio的安卓端手機(jī)播放器設(shè)計(jì)和實(shí)現(xiàn)計(jì)算機(jī)專業(yè)_第3頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/8/5908c390-3c16-4c45-9f4b-0979fb28023a/5908c390-3c16-4c45-9f4b-0979fb28023a3.gif)
![基于Vitamio的安卓端手機(jī)播放器設(shè)計(jì)和實(shí)現(xiàn)計(jì)算機(jī)專業(yè)_第4頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/8/5908c390-3c16-4c45-9f4b-0979fb28023a/5908c390-3c16-4c45-9f4b-0979fb28023a4.gif)
![基于Vitamio的安卓端手機(jī)播放器設(shè)計(jì)和實(shí)現(xiàn)計(jì)算機(jī)專業(yè)_第5頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/8/5908c390-3c16-4c45-9f4b-0979fb28023a/5908c390-3c16-4c45-9f4b-0979fb28023a5.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、題目基于Vitamio的安卓端手機(jī)播放器摘 要快捷、高效的生活節(jié)奏促使當(dāng)今人們獲取消息新聞渠道的即時(shí)性、多元化。隨著網(wǎng)絡(luò)普及率、覆蓋率的不斷擴(kuò)大和網(wǎng)絡(luò)速度的大幅提升,人們?cè)缫蚜?xí)慣通過(guò)移動(dòng)手機(jī)觀看視頻來(lái)了解發(fā)生在當(dāng)下的事情。眾所周知,各大應(yīng)用市場(chǎng)都有各種各樣的基于android系統(tǒng)的播放器。本課題基于安卓系統(tǒng),從實(shí)用性、簡(jiǎn)潔性出發(fā),設(shè)計(jì)一款可以播放本地視頻、獲取服務(wù)端json數(shù)據(jù)以及可接受外部輸入地址的視頻播放器。該視頻播放器是依賴Vitamio SDK,支持小屏與全屏手動(dòng)切換、播放暫停、音量和亮度調(diào)節(jié)、實(shí)時(shí)顯示時(shí)間的功能。從功能需求到理論分析再到具體實(shí)現(xiàn),最終展示實(shí)現(xiàn)效果并且總結(jié)分析不足與收獲
2、。關(guān)鍵詞:android; Vitamio; json; 播放器Android cellphone video player based on the Vitamio SDKABSTRACTOn account of pace of the lifestyle has been quick and convenient, easy and efficient, it is of immediateness and diversity for people who live in this moment to gain news and information. With the popular
3、ity rate and spreading rate of the Internet becoming increased year by year, and the network speed becoming faster and faster, people have been accustomed to realizing and learning about the things which just happened by mobile phone on their hands watching the network videos at any time and in any
4、place.As we all know, there are various video players based on Android system in lots of popular application software markets. The project is also based on Android system. And put the practicability and conciseness as the first, designing a kind of video player which can play local-SDCard videos, ac
5、quire the json datas from windows web server and input known videos URI by users fingers. The next, this article will describe that this player depends on Vitamio SDK and videoview can support a lot of functions, such as switching small-screen or full-screen, achieving play or pause, adjusting volum
6、e or brightness and displaying system time. At last, the order to narrate this project is from function needs to theoretical analysis, from the analysis to the concrete realization, and the end which show final results or phenomena and summarize the harvest and the shorts during this project design.
7、Keywords:android;; Vitamio; json; video player目 錄摘 要iABSTRACTii第一章緒論- 1 -1.1課題背景目的與意義- 1 -1.1.1課題背景- 1 -1.1.2課題的目的及意義- 1 -1.2本文的主要內(nèi)容的結(jié)構(gòu)安排- 2 -第二章軟件的需求及設(shè)計(jì)的準(zhǔn)備- 3 -2.1 軟件需求分析- 3 -2.2 Android知識(shí)準(zhǔn)備- 3 -2.3 關(guān)于Vitamio庫(kù)- 5 -2.2.1 如何將Vitamio庫(kù)放進(jìn)項(xiàng)目工程中?- 5 -2.2.2 Vitamio庫(kù)中有什么?- 6 -2.3 搭建簡(jiǎn)易的Windows Web服務(wù)器- 7 -2.3
8、.1 簡(jiǎn)單搭建- 7 -2.3.2 客戶端如何與服務(wù)端通信?- 7 -第三章軟件設(shè)計(jì)- 8 -3.1 總體框架設(shè)計(jì)- 8 -3.1.1 總體流程圖,各頁(yè)面關(guān)系- 11 -3.2 軟件導(dǎo)航啟動(dòng)頁(yè)設(shè)計(jì)- 13 -3.2.1 流程概括- 13 -3.2.2 代碼思想詳解- 13 -3.2.3 實(shí)現(xiàn)圖解- 16 -3.3 子頁(yè)面之本地視頻- 16 -3.3.1 流程概括- 16 -3.3.2 代碼思想詳解- 17 -3.3.3 實(shí)現(xiàn)圖解- 19 -3.4 子頁(yè)面之本地網(wǎng)絡(luò)- 20 -3.4.1 流程概括- 20 -3.4.2 代碼思想詳解- 21 -3.4.3實(shí)現(xiàn)圖解- 23 -3.5 子頁(yè)面其他非功
9、能性頁(yè)面- 23 -3.5.1 流頁(yè)面部分概述- 23 -3.5.2 關(guān)于我頁(yè)面- 24 -3.6 主要功能基于Vitamio的視頻播放頁(yè)面- 24 -3.6.1 流程概括- 24 -3.6.2 代碼思想詳解- 24 -3.7 應(yīng)用程序清單和布局部分解釋- 27 -第四章測(cè)試部分- 29 -4.1播放頁(yè)面真機(jī)測(cè)試- 29 -4.1.1測(cè)試結(jié)論- 29 -結(jié)束語(yǔ)- 30 -致謝- 31 -參考文獻(xiàn)- 32 -v第一章 緒 論1.1 課題背景目的與意義1.1.1課題背景在信息科技飛速發(fā)展的今天,人們獲取信息、知識(shí)的方式也跟隨著發(fā)生了巨大的變化,便捷了我們的生活。從以前最開始的閱讀書報(bào)來(lái)了解社會(huì)國(guó)家
10、大事,到通過(guò)電視機(jī)觀看新聞,再到出現(xiàn)移動(dòng)數(shù)據(jù)和寬帶網(wǎng)絡(luò),同時(shí)也衍生出的一系列用于人們彼此間進(jìn)行信息接收與交換的移動(dòng)設(shè)備,如平板電腦、筆記本和手機(jī)。這些設(shè)備的屏幕尺寸、分辨率、硬件等方面各不相同,使得具備相同功能(例如視頻播放器)的應(yīng)用,和實(shí)際上在這些設(shè)備上運(yùn)用的應(yīng)用也各有差異。從生活的各個(gè)角落我們都可以看到,無(wú)論是地鐵、公交站臺(tái)的廣告、還是商場(chǎng)廣場(chǎng)的LED屏都播放著各式的視頻。由此可見(jiàn)視頻是傳達(dá)信息的一種便捷、普遍而有效手段。而一款能夠具備穩(wěn)定播放視頻功能的播放器也更容易受到人們的青睞。根據(jù)有關(guān)數(shù)據(jù)顯示,我國(guó)擁有移動(dòng)電話的用戶量呈現(xiàn)增長(zhǎng)趨勢(shì),擁有固定電話的用戶量呈現(xiàn)減小趨勢(shì);移動(dòng)電話用戶大部分
11、都使用3G/4G(移動(dòng)寬帶)1。表明了現(xiàn)如今人們?cè)絹?lái)越追求高速的上網(wǎng)體驗(yàn)??梢苿?dòng)智能設(shè)備應(yīng)用的播放器需要依附于具體的系統(tǒng)。目前手機(jī)端主流的兩種系統(tǒng)有IOS系統(tǒng)和Android系統(tǒng)2。針對(duì)大部分用戶使用手機(jī)端系統(tǒng)的情況,使用Android系統(tǒng)用戶占的比重較大。Android具有的開放性,使得在這個(gè)平臺(tái)上做進(jìn)一步的開發(fā)的可能性就越來(lái)越多3。但由于各個(gè)品牌手機(jī)的主打方向不同,使得手機(jī)硬件也各不相同。硬件上的差異和Android自帶庫(kù)關(guān)于視頻播放編解碼的局限性使得一些格式的視頻不能夠正常播放4。因此,涌現(xiàn)出了一批通過(guò)軟件編解碼能夠最大限度地支持各式視頻格式的視頻開源項(xiàng)目。Vitamio便是眾多用于視頻
12、開發(fā)的開源項(xiàng)目之一,并且因?yàn)樗鼘?duì)于Android系統(tǒng)關(guān)于視頻方面的開發(fā)做得比較好,使得開發(fā)初學(xué)者更愿意使用它。Vitamio幾乎支持所有的常見(jiàn)視頻格式,如mp4、3gp、rtsp、rtmp等等。除此之外,還包含有一些非常人性化的功能,例如優(yōu)化了設(shè)備的CPU和GPU、支持手機(jī)和平板各種移動(dòng)設(shè)備、對(duì)于視頻播放緩沖的支持和播放畫面的調(diào)節(jié)等等5。1.1.2課題的目的及意義當(dāng)前各種樣式的播放器有很多,但抽離掉一些美觀的界面包裝元素,歸結(jié)到底,這些播放器大體上實(shí)現(xiàn)的都是關(guān)于視頻播放的一些基本功能(例如:播放、暫停、音量調(diào)節(jié)和亮度調(diào)節(jié)這些功能)。所以就目前來(lái)說(shuō),能夠依賴一款穩(wěn)定的視頻開源庫(kù),并開發(fā)一款基于A
13、ndroid系統(tǒng)的手機(jī)視頻播放應(yīng)用,是有非常好的應(yīng)用前景的6。對(duì)于可以讓沒(méi)有多少視頻開發(fā)方面經(jīng)驗(yàn)的人能夠輕松上手,有必要運(yùn)用Vitamio SDK來(lái)對(duì)視頻播放的基本功能進(jìn)行設(shè)計(jì)與實(shí)現(xiàn)。1.2 本文的主要內(nèi)容的結(jié)構(gòu)安排本文設(shè)計(jì)的播放器是基于一個(gè)由國(guó)人研發(fā)的Android視頻開源項(xiàng)目Vitamio SDK,能夠播放幾乎所有視頻格式,功能強(qiáng)大,簡(jiǎn)單易用。本文的具體結(jié)構(gòu)安排如下:第一章 緒論:主要介紹該課題的研究背景、目的及意義。第二章 軟件的需求及設(shè)計(jì)準(zhǔn)備:該章主要分析軟件一些功能需求及其設(shè)計(jì)中涉及的所需相關(guān)android知識(shí)儲(chǔ)備,例如:Android組件、Fragment概述、JSON基礎(chǔ)知識(shí)、線
14、程和有關(guān)把Vitamio庫(kù)添加到項(xiàng)目中的方法步驟,還有搭建簡(jiǎn)易的Windows端web端服務(wù)器等等。第三章 軟件設(shè)計(jì):從軟件整體框架著手,逐步介紹各個(gè)子頁(yè)面及主要視頻播放頁(yè)面的設(shè)計(jì)思路、實(shí)現(xiàn)方法及預(yù)期效果。子頁(yè)面的介紹都是依照由大到小、由粗到細(xì)的方法來(lái)進(jìn)行的。第四章 最終實(shí)現(xiàn)及真機(jī)測(cè)試:該部分主要展示最終實(shí)現(xiàn)的效果圖以及真機(jī)測(cè)試的收獲總結(jié)。第二章 軟件的需求及設(shè)計(jì)的準(zhǔn)備2.1 軟件需求分析本課題最主要部分是視頻播放的部分。理論上,需要播放本地格式的視頻和流地址的視頻,并且盡量讓視頻播放的控制頁(yè)面相同。視頻控制頁(yè)面都能控制視頻的播放和暫停,控制視頻音量的大小和亮度的高低。本設(shè)計(jì)對(duì)于視頻可支持的格
15、式要求是,能夠播放rtsp、rtmp和m3u8類型的媒體流,還有mp4、3gp類型的視頻。只需正確使用,Vitamio庫(kù)可以完全支持這些視頻格式。進(jìn)一步地,在能夠成功播放指定要求類型視頻的基礎(chǔ)上,需要應(yīng)用能夠?qū)崿F(xiàn)展示本地視頻并能點(diǎn)擊播放、接收服務(wù)器包含視頻流地址的JSON數(shù)據(jù)并解析,解析完后再展示并實(shí)現(xiàn)點(diǎn)擊播放,手動(dòng)輸入視頻流地址并播放。2.2 android知識(shí)準(zhǔn)備本部分只涉及到本課題所需要的核心android知識(shí),是對(duì)第三章軟件設(shè)計(jì)思想那一部分的補(bǔ)充說(shuō)明,比較零散,覆蓋并不全面。1. ActivityActivity的生命周期:Android四大組件之一:activity,它的生命周期就是
16、一個(gè)從啟動(dòng)時(shí)的創(chuàng)建到最終用完后銷毀的過(guò)程2。#創(chuàng)建一個(gè)Activity時(shí)生命周期的方法執(zhí)行順序:onCreate()->onStart()->onResume();#銷毀Activity時(shí)生命周期的方法執(zhí)行順序:onPause()->onStop()->onDestroy()。#A頁(yè)面跳轉(zhuǎn)到B頁(yè)面,點(diǎn)擊返回,這個(gè)過(guò)程中的生命周期:有B完全覆蓋A和B不完全覆蓋A兩種情況,如下所述。1) 在B頁(yè)面完全覆蓋A頁(yè)面的情況下A跳轉(zhuǎn)B頁(yè)面的生命周期方法執(zhí)行順序onPause(A) ->onCreate(B)->onStart(B)->onResume(B)->
17、;onStop(B);B頁(yè)面點(diǎn)擊后返回生命周期的執(zhí)行順序:onPause(B)->onReStart(A)->onStart(A)->onResume(A)->onStop(B)->onDestroy(B)。2) 在B頁(yè)面不完全覆蓋A頁(yè)面的情況下A跳轉(zhuǎn)B頁(yè)面的生命周期方法執(zhí)行順序:onPause(A)->onCreate(B)->onStart(B)->onResume(B);B頁(yè)面點(diǎn)擊后返回生命周期執(zhí)行順序:onPause(B)->onResume(A)->onStop(B)->onDestroy(B)。#Activity的橫
18、豎屏切換生命周期:默認(rèn)情況:onPause()->onStop()->onDestroy()->onCreate()->onStart()->onResume()。#屏蔽因?yàn)闄M豎屏切換而導(dǎo)致生命周期重新執(zhí)行的解決方法:在清單文件中添加android屬性類型中的configChanges(此屬性用于捕獲手機(jī)狀態(tài)的改變狀況),讓這個(gè)的值為keyboardHidden、screenSize和orientation(這3個(gè)值之間用“|”間隔)。#Activity的跳轉(zhuǎn)利用intent顯示啟動(dòng):新建并實(shí)例化intent;用setClass(此處為當(dāng)前Activity,此處為
19、想要或?qū)⒁D(zhuǎn)的Activity.class);利用startActivity啟動(dòng)跳轉(zhuǎn)。2. Fragment、FrameLayout關(guān)于Fragment:Fragment與Activity相似,一樣有著它們的生命周期。但又不完全相同,因?yàn)橥ǔJ褂肍ragment時(shí),實(shí)際上它像一個(gè)布局中的控件一樣,是被包含在Activity中的,這樣一來(lái)它的生命周期常常會(huì)受到Activity的生命周期的控制。Activity往往通過(guò)Fragment事務(wù)(具體的為:FragmentTransaction)對(duì)Fragment進(jìn)行多個(gè)操作改變的控制7。關(guān)于FrameLayout:幀布局,它是一個(gè)容器;包含在幀布局的
20、組件在其內(nèi)部都占據(jù)一塊區(qū)域,每塊區(qū)域?yàn)橐粠?;android關(guān)于布局的gravity屬性,都會(huì)依照屬性具體值為這些幀找到對(duì)齊的位置8。3. JSON基礎(chǔ)JSON數(shù)據(jù),可以在text文本中進(jìn)行編輯,且能在數(shù)據(jù)交換和傳輸信息效率發(fā)揮較好的作用。通常JSON文件中的內(nèi)容有對(duì)象和數(shù)組兩種結(jié)構(gòu)。JSON對(duì)象由大括號(hào)括起來(lái),里面的內(nèi)容是若干個(gè)鍵值對(duì)key:value組成,鍵值對(duì)間用逗號(hào)分隔開;key為屬性,value為屬性值(類型可以為數(shù)字、字符串、數(shù)組、對(duì)象);可以通過(guò)對(duì)象.key的方式獲取屬性值9。JSON數(shù)組由中括號(hào)括起來(lái),數(shù)組中可以包含多個(gè)JSON對(duì)象。JSON文件的后綴名是“.json”,MIME
21、類型是application/json。4. Handler線程Handler存在的意義是它被用于傳遞并處理消息,可以為android主線程分?jǐn)偩徑庀⑻幚淼膲毫?。一般情況下,Handler主要用于在新啟動(dòng)線程中發(fā)送消息,在主線程中獲取并處理接收到的消息。Handler類中包含關(guān)于發(fā)送處理消息的函數(shù)方法,主要有如下:sendEmptyMessage(int what):此方法用于發(fā)送空消息,what的值可以是任意整型數(shù)。void handleMessage(Message msg):此方法通常被重寫,和被用于接收、處理消息。final boolean sendEmptyMessageDelay
22、ed(int what, long delayMillis):經(jīng)過(guò)多少毫秒后發(fā)送空消息。final boolean sendMessage(Message msg):發(fā)送消息。5. Http協(xié)議圖 1Http請(qǐng)求-響應(yīng)模型由上圖的Http請(qǐng)求-響應(yīng)模型可知,http協(xié)議最基礎(chǔ)的模式是:客戶端發(fā)送請(qǐng)求消息,服務(wù)端返回響應(yīng)消息。本課題中,客戶端(手機(jī)端)利用已知的URL地址,對(duì)服務(wù)端發(fā)送請(qǐng)求(常用請(qǐng)求有:GET和POST),服務(wù)端返回響應(yīng)碼給客戶端。通常響應(yīng)碼有:200-OK-請(qǐng)求成功、400-Bad Request-客戶端請(qǐng)求語(yǔ)法錯(cuò)誤、404-Not Found-請(qǐng)求資源地址(URL錯(cuò)誤)不存在
23、等等。2.3 關(guān)于Vitamio庫(kù)2.2.1 如何將Vitamio庫(kù)放進(jìn)項(xiàng)目工程中?以下步驟是基于AndroidStudio環(huán)境中添加Vitamio庫(kù)到項(xiàng)目工程文件里,完全個(gè)人摸索添加進(jìn)工程,具體如下:a.首先,簡(jiǎn)單講一下庫(kù)的下載及從Vitamio官方下載中心(網(wǎng)址:/Download/),下載AndroidStudio版的Vitamio5.2.3的壓縮包。解壓的壓縮包中有Vitamio庫(kù)文件夾和Vitamio-Sample文件夾。b.將Vitamio庫(kù)文件夾直接復(fù)制粘貼進(jìn)項(xiàng)目工程中,修改Vitamio文件夾下的build.gradle的Compil
24、eSdkVersion為25、buildToolsVersion為“25.0.0”、minSDKVersion為14、targetSdkVersion為25,盡量將CompileSdkVersion、buildToolsVersion和targetSdkVersion版本號(hào)保持一致。c.在主工程下的setting.gradle添加includevitamio。d.在依賴vitamio的module文件目錄下的build.gradle中dependencies里添加compile project(:vitamio)。e.在module的manifest.xml文件中添加幾個(gè)權(quán)限<uses-
25、permission>(WAKE_LOCK/INTERNET/ACCESS_NETWORK_STATE/READ_EXTERNAL_STORAGE)。并且一定要在manifest文件中初始化vitamio。具體如下:<!-必須初始化-><activityandroid:name="io.vov.vitamio.activity.InitActivity" android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navig
26、ation"android:launchMode="singleTop"android:theme="android:style/Theme.NoTitleBar"android:windowSoftInputMode="stateAlwaysHidden"/>2.2.2 Vitamio庫(kù)中有什么?本部分只是針對(duì)于該設(shè)計(jì)涉及到內(nèi)容的部分介紹,所以并不十分全面。MediaPlayer類,用于控制音頻或者視頻和網(wǎng)絡(luò)流,可以從videoview中找到使用這個(gè)類的方法并使用需要的方法10。大部分情況下用法與android.me
27、dia.MediaPlayer相似。MediaPlayer里存在一個(gè)監(jiān)聽器OnInfoListener,當(dāng)有視頻緩沖信息警告和錯(cuò)誤時(shí)調(diào)用該監(jiān)聽。在這個(gè)監(jiān)聽中可以利用這些進(jìn)一步處理發(fā)生的情況,分別有:開始緩沖(MEDIA_INFO_BUFFERING_START)、緩沖結(jié)束(MEDIA_INFO_BUFFERING_END)、下載速率變化(MEDIA_INFO_DOWNLOAD_RATE_CHANGED)。MediaPlayer里存在一個(gè)監(jiān)聽器OnBufferingUpdateListener,當(dāng)播放網(wǎng)絡(luò)視頻流時(shí),且視頻緩沖發(fā)生變化時(shí)調(diào)用該監(jiān)聽器。public void setVideoURI(
28、Uri uri):該方法用于設(shè)置視頻播放地址。public void setBufferSize(int bufSize):該方法用于設(shè)置視頻緩沖大小。public void setVideoQuality(int quality):該方法用于設(shè)置視頻播放畫質(zhì)。public void setOnInfoListener(OnInfoListener l):該方法用于設(shè)置視頻緩沖時(shí)的信息。VideoView中的存在一些方法: setVideoLayout方法,可以用來(lái)設(shè)置拉伸、全屏、鋪滿等視頻播放界面布局;pause方法可以用來(lái)暫停視頻播放;start方法可以用來(lái)恢復(fù)暫停的視頻,并繼續(xù)播放視頻。
29、2.3 搭建簡(jiǎn)易的Windows Web服務(wù)器2.3.1 簡(jiǎn)單搭建在Windows電腦中,首先找到并打開“Internet信息服務(wù)(IIS)管理器”,找到在自己計(jì)算機(jī)名稱目錄下的子項(xiàng)“網(wǎng)站”,右鍵新建網(wǎng)站。一般默認(rèn)情況下,需要將想要通過(guò)web網(wǎng)頁(yè)讀取的文件放置在默認(rèn)路徑,例如:C:inetpubMyWeb。這里的MyWeb是自己新建的,為了區(qū)分其他文件夾,里面用于存放通過(guò)web讀取處理的文件。然后,在彈出的添加網(wǎng)站窗口中,填寫網(wǎng)站名稱、應(yīng)用程序池和物理路徑(選擇MyWeb目錄下的路徑),再下拉選擇綁定地址和填寫端口號(hào)。此時(shí)若點(diǎn)擊“啟動(dòng)網(wǎng)站”,可以看到之前目錄下存放的文件,也能成功的在瀏覽器里打
30、開并查看文件。特別地,由于本實(shí)驗(yàn)是存放JSON類型的文件。如果沒(méi)有在MMIE類型中添加相應(yīng)關(guān)于JSON的設(shè)置,瀏覽器將不能成功查看該JSON文件內(nèi)容。進(jìn)入MMIE類型設(shè)置,添加擴(kuò)展名為.json,修改MMIE類型為text/JSON,修改條目類型為本地。2.3.2 客戶端如何與服務(wù)端通信?在簡(jiǎn)單搭建電腦Web服務(wù)端之后,需要了解一下Android客戶端與Windows服務(wù)端通信的方式。本設(shè)計(jì)中客戶端與服務(wù)端的通信依賴http協(xié)議。在Android的庫(kù)中,存在一個(gè). HttpURLConnection的類,此類可以訪問(wèn)http資源。大體上是先發(fā)送一個(gè)請(qǐng)求,然后將請(qǐng)求的數(shù)據(jù)以流的形式讀取回來(lái)。具體
31、流程:創(chuàng)建一個(gè)URL對(duì)象用于指向需要請(qǐng)求數(shù)據(jù)的所在位置;利用HttpURLConnection實(shí)例化的對(duì)象從網(wǎng)絡(luò)中獲取請(qǐng)求后服務(wù)器返回的數(shù)據(jù);設(shè)置連接超時(shí);對(duì)服務(wù)器響應(yīng)發(fā)回的碼進(jìn)行判斷;如果返回的是代表獲取成功的響應(yīng)碼,就說(shuō)明成功獲得了網(wǎng)絡(luò)中返回的數(shù)據(jù)流。第三章 軟件設(shè)計(jì)3.1 總體框架設(shè)計(jì)一個(gè)Android軟件功能的實(shí)現(xiàn)通常由布局xml文件和若干個(gè)Java代碼文件組成。本應(yīng)用整體布局框架由Drawerlayout、Navigation和Basepager組成。本應(yīng)用整體操作流程簡(jiǎn)述:手機(jī)桌面點(diǎn)擊起始啟動(dòng)頁(yè)面過(guò)后進(jìn)入歡迎面,然后進(jìn)行具體功能項(xiàng)選擇。經(jīng)過(guò)啟動(dòng)頁(yè)面之后,用戶就正式進(jìn)入應(yīng)用。首先映入
32、眼簾的是歡迎界面,歡迎界面由一個(gè)圖片和一句話組成。隨后,用戶用手指從屏幕的左端向右滑動(dòng)(或者用手指點(diǎn)擊屏幕左上角的圖標(biāo))展開本應(yīng)用的菜單,然后點(diǎn)擊選擇各個(gè)子功能。若想要關(guān)閉菜單,可以用手指左滑(或者點(diǎn)擊屏幕右側(cè)陰影處)。抽屜布局(DrawerLayout)是出自android官方自帶的V4包,即android.support.v4.widget.DrawerLayout。導(dǎo)航視圖(NavgavitionView)則是出自android中自帶的design包,即(android.support.design.widget.NavigationView)。圖 2核心視圖布局框架展示圖從上圖,可以顯
33、而易見(jiàn)地看出導(dǎo)航視圖(NavigationView)位于抽屜布局(DrawerLayout)中的左側(cè)部分;導(dǎo)航視圖的寬度是小于抽屜布局內(nèi)容布局的寬度的。導(dǎo)航視圖布局由一個(gè)自定義的頭部布局(包含一張圖)和一個(gè)menu組成。展開說(shuō)明如下:NavigationView布局中設(shè)置android:layout_gravity="start"(或值為“l(fā)eft”)屬性,表示其在抽屜布局的左邊。在右滑(打開菜單)和左滑(收起菜單)時(shí),需要保證手機(jī)屏幕頂部的狀態(tài)欄(statusbar)的背景統(tǒng)一。打開菜單時(shí)跟隨系統(tǒng)背景,關(guān)閉菜單時(shí)是透明色。可以通過(guò)在樣式文件中添加兩個(gè)屬性在主題中,設(shè)置an
34、droid:windowDrawsSystemBarBackgrounds的值為true,設(shè)置android:statusBarColor的值為android:color/transparent。前者表示,應(yīng)用程序的主題(theme)是通過(guò)繼承而來(lái)的,需要確保系統(tǒng)能繪制狀態(tài)欄(statusbar);后者表示,狀態(tài)欄設(shè)置為透明狀態(tài),此時(shí)的狀態(tài)欄系統(tǒng)無(wú)法控制就交由抽屜布局控制。在代碼中抽屜布局設(shè)置,可以通過(guò)setStatusBarBackgroundColor設(shè)置此時(shí)statusbar的顏色,同時(shí)抽屜布局文件中也要添加android:fitsSystemWindows="true&quo
35、t;屬性。導(dǎo)航視圖中菜單欄的各個(gè)菜單項(xiàng)(item)需要具備每一項(xiàng)的獨(dú)立性。為了在點(diǎn)擊事件發(fā)生時(shí),能夠正確跳到各項(xiàng)功能頁(yè)面。因此在menu布局中,可以設(shè)置各個(gè)Item標(biāo)簽所在group的屬性checkableBehavior值為single,或者也可以添加每一個(gè)item標(biāo)簽的屬性checkable值為: true。在選擇菜單項(xiàng)中各項(xiàng)功能時(shí),為了方便用戶在打開抽屜時(shí)知曉當(dāng)前選擇了哪一項(xiàng),通過(guò)如下思路,為菜單每一項(xiàng)設(shè)置了改變顏色狀態(tài)(菜單項(xiàng)中包含圖片和文字顏色統(tǒng)一都改變,選中時(shí)是藍(lán)色,未選中的為灰色),具體思路如下:設(shè)置兩個(gè)數(shù)組,一個(gè)二維數(shù)組(用于保存選中與未選中狀態(tài))由兩個(gè)一維數(shù)組組成,另一個(gè)數(shù)組
36、用于保存選中時(shí)的顏色和未選中時(shí)的顏色;將兩個(gè)數(shù)組放在顏色狀態(tài)列表(ColorStateList)里;導(dǎo)航視圖分別設(shè)置菜單項(xiàng)圖標(biāo)顏色和文字顏色。關(guān)于點(diǎn)擊每一個(gè)菜單項(xiàng)在屏幕底部出現(xiàn)短暫顯示的提示條??梢岳肧nackbar,它是一種類似于Toast和Dialog的,具有反饋性的控件。它能夠出現(xiàn)在手機(jī)屏幕中所有視圖的上方,并且顯示一段時(shí)間后自動(dòng)消失。實(shí)現(xiàn)應(yīng)用的各個(gè)功能需要以頁(yè)面的方式展示,每一個(gè)頁(yè)面都存在于一個(gè)fragment中。每一個(gè)頁(yè)面都有一個(gè)共通點(diǎn),即都是由視圖和數(shù)據(jù)處理實(shí)現(xiàn)相應(yīng)功能的?,F(xiàn)將各個(gè)子頁(yè)面繼承自一個(gè)基類。通過(guò)創(chuàng)建一個(gè)抽象公共類BasePager作為子頁(yè)面的基類(或者說(shuō)父類)。該類中
37、,創(chuàng)建一個(gè)View用于接受各個(gè)子頁(yè)面返回的實(shí)例、創(chuàng)建context用于在構(gòu)造方法中通過(guò)上下文與頁(yè)面視圖去實(shí)現(xiàn)同一個(gè)initView抽象方法,進(jìn)而實(shí)現(xiàn)各個(gè)子頁(yè)面的視圖。BasePager中還存在兩個(gè)方法分別是initView和initData。 initView抽象化的目的是使得每個(gè)子類頁(yè)面必須通過(guò)實(shí)現(xiàn)該方法才能實(shí)現(xiàn)頁(yè)面。initData是一個(gè)沒(méi)有返回值的公共方法,其目的是當(dāng)頁(yè)面中存在數(shù)據(jù)綁定(例如listView綁定適配器)時(shí)處理該方法。此外,還要在該類中設(shè)置一個(gè)布爾類型的變量isInitData用于避免出現(xiàn)頁(yè)面數(shù)據(jù)重復(fù)初始化。在Activity中創(chuàng)建一個(gè)BasePager類型的數(shù)組(Arra
38、yList),用來(lái)存放子頁(yè)面。設(shè)置整型變量position,用來(lái)標(biāo)記子頁(yè)面在數(shù)組中位置。展開說(shuō)明如下:為導(dǎo)航視圖(NavigationView)的菜單項(xiàng)設(shè)置監(jiān)聽,用于跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面。在監(jiān)聽事件中,通過(guò)判斷每個(gè)子菜單的id來(lái)區(qū)分每個(gè)頁(yè)面,與此同時(shí)給每一頁(yè)面設(shè)置一個(gè)position值。例如,當(dāng)點(diǎn)擊“本地視頻”頁(yè)面時(shí)position值為0,點(diǎn)擊“本地網(wǎng)絡(luò)”頁(yè)面時(shí)position值為1,點(diǎn)擊“流”頁(yè)面時(shí)position值為2,點(diǎn)擊“關(guān)于我”頁(yè)面時(shí)position值為3。之后,經(jīng)過(guò)每一次判斷子頁(yè)面,得到頁(yè)面位置position后,需要將頁(yè)面放入放入fragment中。單獨(dú)創(chuàng)建兩個(gè)私有類型的方法setFr
39、agment和getBasePager。setFragment的作用是在acitivity中把頁(yè)面添加到fragment中。getBasePager的作用是根據(jù)position位置得到該位置所對(duì)應(yīng)的頁(yè)面。核心代碼:private void setFragment() /1.得到FragmentMangerFragmentManager manager = getSupportFragmentManager();/2.開啟事務(wù)FragmentTransaction ft = manager.beginTransaction();/3.替換容器內(nèi)的fragmentft.replace(R.id.f
40、l_main_content,new TestFragment(getBasePager();/4.提交事務(wù)mit();代碼中,R.id.fl_main_content是一個(gè)幀布局的布局資源id,用來(lái)存放每一個(gè)實(shí)例化fragment子頁(yè)面的布局。此外,各個(gè)子頁(yè)面顯示的內(nèi)容布局也都是幀布局(FrameLayout)。FragmentManager一般被用于在activity中管理fragment。需要注意,F(xiàn)ragment類必須實(shí)例化為單獨(dú)的類TestFragment,否則出錯(cuò)。附加退出程序的小功能,在activity中重寫onKeyDown方法,判斷是否有按下鍵,創(chuàng)建系統(tǒng)自帶主題的對(duì)話框(al
41、ertdialog)用于提醒用戶是否退出程序。在對(duì)話框中,用setTitle設(shè)置對(duì)話框標(biāo)題,setMessage設(shè)置消息信息,添加兩個(gè)按鈕(一個(gè)退出,一個(gè)回到程序)并設(shè)置按鈕監(jiān)聽。3.1.1 總體流程圖,各頁(yè)面關(guān)系圖 3軟件總體框架流程圖圖 4軟件總體子頁(yè)面關(guān)系流程圖圖 5子頁(yè)面布局關(guān)系圖3.2 軟件導(dǎo)航啟動(dòng)頁(yè)設(shè)計(jì)3.2.1 流程概括為了給用戶提供一個(gè)更好的體驗(yàn),通常需要給應(yīng)用程序添加一個(gè)導(dǎo)航頁(yè)面。當(dāng)打開視頻播放器時(shí),頁(yè)面全屏循環(huán)播放小視頻。用手指滑動(dòng)頁(yè)面,就會(huì)全屏循環(huán)播放另一個(gè)小視頻。當(dāng)用戶處在啟動(dòng)頁(yè)面,不小心點(diǎn)擊返回鍵,在屏幕下方會(huì)彈出Toast提示條“再按一次退出”。如果沒(méi)有再按返回鍵,
42、可以繼續(xù)。點(diǎn)擊第三個(gè)頁(yè)面中的“立即體驗(yàn)”,用戶算是進(jìn)入視頻播放器內(nèi)部,進(jìn)行播放器選擇功能的體驗(yàn)。3.2.2 代碼思想詳解實(shí)現(xiàn)導(dǎo)航啟動(dòng)頁(yè)的是ViewPagerActivity。ViewPagerActivity繼承自FragmentActivity并且設(shè)置實(shí)現(xiàn)ViewPager類下的OnPagerChangeListener(監(jiān)聽頁(yè)面改變)接口。在該activity被onCreate創(chuàng)建方法中分別執(zhí)行initView(頁(yè)面初始化)和initDots(初始化“小點(diǎn)”)。其中,initView方法用于在activity中獲取ViewPager布局文件內(nèi)容、實(shí)例化三個(gè)fragment、創(chuàng)建并設(shè)置Vie
43、wPager適配器和添加ViewPager的頁(yè)面改變監(jiān)聽。initDots方法的作用是,設(shè)置滑動(dòng)三個(gè)頁(yè)面時(shí),那三個(gè)ImageView(點(diǎn))的狀態(tài)動(dòng)態(tài)改變實(shí)現(xiàn)。動(dòng)態(tài)改變?nèi)齻€(gè)ImageView具體關(guān)鍵代碼及思路如下:1. 獲取三個(gè)ImageView所處父集合(ViewGroup)的布局線性布局。利用循環(huán),依次從布局文件中獲取三個(gè)ImageView,并賦給事先創(chuàng)建好的ImageView類型數(shù)組,且每個(gè)ImageView都設(shè)為默認(rèn)灰色,默認(rèn)第一個(gè)ImageView為白色,代表選中狀態(tài);2. 為使其他ImageView狀態(tài)能夠改變,創(chuàng)建一個(gè)方法setCurrentDot的方法,并將其設(shè)置在onPageS
44、elected(可以為其傳遞一個(gè)當(dāng)前選中的位置,暫且為設(shè)變量position)中;3. 對(duì)于setCurrentDot方法,如果傳遞過(guò)來(lái)的position不等于currentIndex且沒(méi)有越出三個(gè)的個(gè)數(shù)范圍(position在02之間),就將之前被選中的ImageView(位置為currentIndex)顏色設(shè)為默認(rèn)灰色,當(dāng)前選中“點(diǎn)”(position)顏色設(shè)為白色,并將position賦給currentIndex,為下一次狀態(tài)改變做準(zhǔn)備。簡(jiǎn)單介紹一下ViewPager.OnPagerChangeListener:該接口下有三個(gè)方法,分別是onPageScrollStateChanged(
45、如果滑動(dòng)狀態(tài)改變時(shí)調(diào)用)、onPageScrolled(如果當(dāng)前頁(yè)面被滑動(dòng)時(shí)調(diào)用)和onPageSelected(如果新的頁(yè)面被選中時(shí)調(diào)用)。導(dǎo)航頁(yè)面(ViewPager)本身是由三個(gè)fragment的集合(List<fragment>)組成,分別為frament1、fragment2、fragment3。為了避免三個(gè)fragment重疊的問(wèn)題,使用ViewPagerAdapter(繼承自FragmentPagerAdapter),給ViewPager設(shè)置適配器。三個(gè)fragment中播放短視頻思路:1. 整體概述:三個(gè)fragment都是通過(guò)調(diào)用自定義的VideoView播放工程
46、下raw目錄中的3個(gè)短視頻。不同的是,第三個(gè)fragment中添加了Button控件,用于跳轉(zhuǎn)到下一個(gè)activity。2. 在每個(gè)fragment中的onCreateView方法中,首先,獲取以View為格式的對(duì)應(yīng)布局(前提是,每個(gè)布局中包含自定義VideoView的布局)。然后,通過(guò)view.findViewById()獲取布局文件里VideoView,為其設(shè)置播放路徑并播放。3. 最后,設(shè)置VideoView播放完成監(jiān)聽,并通過(guò)監(jiān)聽實(shí)現(xiàn)視頻的自動(dòng)循環(huán)播放。關(guān)鍵代碼:public void onCompletion(MediaPlayer mp) videoview.start();/播放
47、完,再一次重頭播放 4. fragment3中通過(guò)一個(gè)按鈕控件跳轉(zhuǎn),跳轉(zhuǎn)后要將導(dǎo)航頁(yè)的activity銷毀,關(guān)鍵跳轉(zhuǎn)代碼如下:Intent intent = new Intent(getActivity(), NavigationViewActivity.class);getActivity().startActivity(intent);getActivity().finish();/銷毀activity關(guān)于自定義的播放視頻頁(yè)面的說(shuō)明,出于其功能需求單一(僅僅播放幾秒鐘的小視頻),所以將其繼承自android.widget.videoview。為了能夠使視頻界面能夠豎直滿屏的播放,在自定義的
48、videoview中重寫了onMesure方法,用于重新計(jì)算視頻的寬高(getDefaultSize)并存儲(chǔ)視頻的寬高(setMeasuredDimension);重寫setOnPreparedListener用于當(dāng)視頻被加載且準(zhǔn)備播放的情況。除此之外,為了防止在啟動(dòng)程序時(shí)人為誤觸導(dǎo)致意外退出,在導(dǎo)航頁(yè)添加了返回鍵監(jiān)聽。當(dāng)初次點(diǎn)觸返回鍵時(shí),會(huì)利用Toast彈出提示“再按一次退出程序”,以提醒用戶;當(dāng)再次點(diǎn)觸返回鍵時(shí),將立即退出應(yīng)用程序。具體想法如下:通過(guò)導(dǎo)航頁(yè)所在的activity中重寫onKeyDown方法,在該方法下先判斷是否有按鍵被按下。如果有,再判斷,按下的鍵是否是返回鍵且僅按一次。如
49、果是,就再次判斷下一次按下的時(shí)間距離上一次按下時(shí)間是否間隔超過(guò)2秒,超過(guò)的話就不退出,沒(méi)超過(guò)就退出。關(guān)鍵代碼:Override public boolean onKeyDown(int keyCode, KeyEvent event) if (event.getAction()=KeyEvent.ACTION_DOWN) if (keyCode=KeyEvent.KEYCODE_BACK && event.getRepeatCount()=0) isExit(); return true; return false; private void isExit() if (Syst
50、em.currentTimeMillis() - mExitTime >2000) Toast.makeText(this,"再按一次退出程序",Toast.LENGTH_SHORT).show(); mExitTime=System.currentTimeMillis(); else finish(); System.exit(0); 注: getRepeatCount函數(shù)返回的值是計(jì)算重復(fù)觸摸或按鍵的次數(shù),有一次即返回值為0;mExitTime的作用是獲得當(dāng)前按鍵事件發(fā)生的時(shí)間。3.2.3 實(shí)現(xiàn)圖解圖 6啟動(dòng)頁(yè)面實(shí)際效果圖3.3 子頁(yè)面之本地視頻3.3.1 流程概
51、括進(jìn)入應(yīng)用后,初次選擇本地視頻頁(yè)面會(huì)有一個(gè)加載視頻等待的過(guò)程,根據(jù)視頻個(gè)數(shù)的多少,處理時(shí)間不同。然后展現(xiàn)出所有本地視頻列表,每一項(xiàng)包含一個(gè)代表視頻的圖標(biāo)、視頻的名稱、視頻的時(shí)長(zhǎng)、視頻占內(nèi)存大小。點(diǎn)擊任意一項(xiàng)即可立即進(jìn)入該視頻的播放頁(yè)面。圖 7本地視頻布局頁(yè)面圖3.3.2 代碼思想詳解從本地的SDCard得到本地視頻數(shù)據(jù),通常的解決方法是遍歷所有視頻類型的后綴名,但是過(guò)于繁瑣,效率較低。為提高獲取效率,可以根據(jù)內(nèi)容提供者,從中獲取視頻信息。在子線程中獲取本地視頻信息,將獲取的本地視頻信息放入集合中。安卓系統(tǒng)中存在一個(gè)內(nèi)容提供者,它通常包含聯(lián)系人信息、系統(tǒng)中的音視頻信息等等。既然有提供者,相輔相成
52、地也存在著內(nèi)容解析者。要想獲得手機(jī)SDCard上的視頻信息,首先得知道它所在內(nèi)容提供者的Uri。查詢Android相關(guān)技術(shù)文檔,得到SDCard中視頻屬于外部存儲(chǔ)器,其內(nèi)容提供者Uri為:MediaStore.Video.Media.EXTERNAL_CONTENT_URI。其次用一個(gè)數(shù)組存放想要查詢的具體數(shù)據(jù)列名。最后調(diào)用內(nèi)容解析者的query方法,遍歷查詢特定列名的數(shù)據(jù)。根據(jù)query方法返回的是一個(gè)光標(biāo)(光標(biāo)Cursor指向列名),當(dāng)不存在視頻時(shí),光標(biāo)會(huì)返回為空。再利用Cursor.moveToNext循環(huán)獲得視頻的名稱、時(shí)長(zhǎng)、文件大小及視頻的絕對(duì)地址。將獲取到的視頻信息字段裝入一個(gè)Be
53、an類(MediaItem)中,方便接下來(lái)對(duì)于各個(gè)信息的設(shè)置及獲得。每一MediaItem代表一條視頻。一般情況下,獲取的視頻不止一條,可將各個(gè)視頻信息放入一個(gè)MediaItem類型的數(shù)組集合中。光標(biāo)Cursor每循環(huán)一次,創(chuàng)建一個(gè)MediaItem(即,一條視頻信息,MediaItem中利用Setter方法設(shè)置視頻信息),然后再將MediaItem添加進(jìn)數(shù)組集合里。當(dāng)光標(biāo)指到下一列名為空時(shí),跳出循環(huán),并且釋放光標(biāo)。此時(shí)所有本地視頻已經(jīng)取完。將所有本地視頻信息以列表ListView的形式展示在手機(jī)屏幕里。沒(méi)有視頻的時(shí)候展示“沒(méi)有本地視頻”的視圖,有視頻的時(shí)候展示視頻列表。當(dāng)在子線程中才處理完獲
54、取視頻的部分后,不管有沒(méi)有視頻,都需要通過(guò)handler發(fā)送一個(gè)空消息(Message)給主線程。一般當(dāng)handler需要處理多種情況時(shí),才會(huì)發(fā)送非空消息。主線程接收到子線程消息后,負(fù)責(zé)處理設(shè)置ListView適配器和在有無(wú)數(shù)據(jù)時(shí)的文本控件顯示。主線程中,當(dāng)有視頻數(shù)據(jù)時(shí)設(shè)置適配器且隱藏布局中文本,當(dāng)沒(méi)有數(shù)據(jù)時(shí)顯示布局中的文本。有一個(gè)小細(xì)節(jié),無(wú)論有沒(méi)有數(shù)據(jù)都需要隱藏ProgressBar,否則會(huì)一直存在,影響用戶觀感。本地視頻頁(yè)面適配器因?yàn)槊恳粋€(gè)視頻頁(yè)面的基類都是BasePager,所以頁(yè)面的適配器需要繼承自BaseAdapter。單獨(dú)自定義一個(gè)本地視頻列表Adapter適配器的類:為了方便在在
55、其他地方實(shí)例化自定義的適配器,在類中運(yùn)用構(gòu)造方法。在該適配器中需要重寫4個(gè)方法:getCount,getItem,getItemId,getView。下面簡(jiǎn)單介紹一下這四種方法:getCount():該方法的返回值控制該Adapter將會(huì)包含列表項(xiàng)的個(gè)數(shù)。getItem(int position):該方法的返回值決定第position處的列表項(xiàng)的內(nèi)容。getItemId(int position):該方法的返回值決定第position處的列表項(xiàng)的ID。getView(int position ,View convertView ,ViewGroup parent):該方法的返回值決定第posi
56、tion處的列表項(xiàng)組件。ListView顯示列表的本質(zhì)是一個(gè)一個(gè)子項(xiàng)顯示的。每一個(gè)子項(xiàng)的顯示都需要適配器調(diào)用它的getView方法。getView方法返回的是每個(gè)子項(xiàng)的視圖。創(chuàng)建視圖需要用到inflate方法加載布局文件。如果子項(xiàng)的個(gè)數(shù)特別多,會(huì)占用內(nèi)存,進(jìn)一步會(huì)影響每一個(gè)子項(xiàng)加載的速度。其中g(shù)etView方法中convertView視圖,表示ListView上滑時(shí)超出手機(jī)屏幕顯示的子項(xiàng)(item)的視圖。通常情況下,因?yàn)榛瑒?dòng)列表而超出屏幕的convertView視圖會(huì)被緩存,所以可以在getView方法中重用convertView視圖來(lái)節(jié)省一部分內(nèi)存消耗。在getView方法中,判斷conv
57、ertView視圖是否為空。如果是,用inflate創(chuàng)建出一個(gè)子項(xiàng)視圖,然后通過(guò)findViewById方法找到控件加載視圖數(shù)據(jù),再將視圖數(shù)據(jù)返回到底層展示出來(lái)。從中得到,在資源文件中同一個(gè)id,會(huì)在每一次調(diào)用getView方法的時(shí)候重新查找該id的控件和給控件賦值及其他重復(fù)性操作。由于在getView方法中已經(jīng)存在查找控件的操作,通過(guò)在適配器類中構(gòu)建一個(gè)內(nèi)部靜態(tài)類ViewHolder(靜態(tài)類只會(huì)在初次加載時(shí)耗時(shí),之后就會(huì)快很多),該類中的變量類型與視頻子項(xiàng)中控件類型一致。再把子項(xiàng)的控件放入ViewHolder中,然后利用view.setTag將此時(shí)的ViewHolder類作為view類型存入到子
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年代保管檔案協(xié)議(2篇)
- 2025年企業(yè)單位雇傭合同模板(2篇)
- 2025年買賣合作廉潔協(xié)議經(jīng)典版(2篇)
- 2025年交通事故自行協(xié)商協(xié)議(三篇)
- 2025年個(gè)人汽車貸款擔(dān)保合同簡(jiǎn)單版(2篇)
- 地鐵項(xiàng)目居間合同協(xié)議書
- 八年級(jí)大考數(shù)學(xué)試卷
- 幼兒園全包裝修合同條款
- 沙石運(yùn)輸誠(chéng)信體系建設(shè)合同
- 樂(lè)器運(yùn)輸協(xié)調(diào)協(xié)議
- 2024年微生物檢測(cè)試劑行業(yè)商業(yè)計(jì)劃書
- 河南開封介紹課件
- 通信設(shè)備售后服務(wù)方案
- 高中英語(yǔ)選擇性必修一單詞表
- 初中生物校本課程綱要
- 物業(yè)公司介紹
- 賣花生混聲合唱簡(jiǎn)譜
- 數(shù)學(xué)方法在物理中的應(yīng)用
- 【永輝超市公司員工招聘問(wèn)題及優(yōu)化(12000字論文)】
- 心肺復(fù)蘇指南
- 《智能物聯(lián)網(wǎng)導(dǎo)論》AIoT導(dǎo)論-第2章課件
評(píng)論
0/150
提交評(píng)論