android教程之開發(fā)移動 web ajax 應(yīng)用_第1頁
已閱讀1頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、Android教程之開發(fā)移動 Web Ajax 應(yīng)用,簡介手機(jī)瀏覽器與 WebKit手機(jī)瀏覽器上的 AjaxWebKit 博客清單 1. Feed 類清單 2. News 類清單 3. Item 類清單 4. web.xml 配置文件Ajax 構(gòu)建的用戶接口清單 5. index.html 文件清單 6. loadEntries 函數(shù)清單 7. addEntry 函數(shù)使用本地存儲進(jìn)行緩存清單 8. 保存到本地存

2、儲清單 9. 從本地存儲加載數(shù)據(jù)清單 10. 添加緩存到 loadEntries 函數(shù),簡介,盡管受到媒體追捧,但是開發(fā)移動設(shè)備應(yīng)用很多年來一直都是高投入、低回報(bào)的工作。 基于 iPhone OS 和 Google Android 的最新一代智能手機(jī)提供了一個更簡單的應(yīng)用開發(fā)方法:Web 應(yīng)用。 這種一次編譯就可以支持所有設(shè)備的方法可以降低開發(fā)成本。更重要的是, 所有這些高端設(shè)備都具備支持高級 HTML、JavaScript 和 C

3、SS 的超現(xiàn)代的瀏覽器。在本文中, 我們將學(xué)習(xí)如何開發(fā)充分利用現(xiàn)代智能手機(jī)功能的廣泛使用 Asynchronous JavaScript and XML (Ajax) 技術(shù)的應(yīng)用。 我們將不僅能了解到如何發(fā)揮這些設(shè)備的最大功效,同時還能學(xué)習(xí)到如何處理它們之間的細(xì)微差別。,,本文闡述如何開發(fā)一個運(yùn)行在 Apple iPhone 以及基于 Android 的智能手機(jī)上的移動 Web 應(yīng)用。 開發(fā)這些設(shè)備上的移動 Web 應(yīng)用,我們不能使用平

4、常的桌面瀏覽器,至少不能完全只使用桌面瀏覽器。 我們還需要模擬器或?qū)嶋H的設(shè)備。對于 iPhone 來說,我們需要使用 iPhone 模擬器。它是 iPhone SDK 的一部分。本文所使用的是 iPhone SDK 3.1。類似地,我們也需要使用 Android SDK。它包含了一個 Android Virtual Device 管理器,這個管理器可以用來創(chuàng)建運(yùn)行各個 Android 版本的 Android 模擬器。 其中本文使用的是

5、Android SDK 2.1。本文所用到的大部分代碼是 JavaScript 代碼,以及一些 HTML 和 CSS。 此外,應(yīng)用還有一個使用 Java? 實(shí)現(xiàn)的服務(wù)器端。這并不是強(qiáng)制性要求的,和其它的 Web 應(yīng)用一樣, 我們可以自己選擇使用任意的服務(wù)器端技術(shù)。我們需要使用 Java 1.6 來運(yùn)行本文所開發(fā)的應(yīng)用。 另外我們還需要使用 Jersey,它是 JAX-RS 的參考實(shí)現(xiàn),以及所有相關(guān)的 Java Archive (JAR)

6、 文件。,手機(jī)瀏覽器與 WebKit,移動設(shè)備很多年就有 Web 瀏覽器了。然而,由于 Web 開發(fā)人員必須處理跨瀏覽器支持問題, 因此開發(fā)瀏覽器應(yīng)用一直是很困難的。開發(fā)人員需要花費(fèi)很多的時間來實(shí)現(xiàn) HTML、JavaScript 和 CSS 在不同版本的瀏覽器上運(yùn)行完全一致,如 Internet Explorer、Mozilla Firefox、Safari 等。 而桌面瀏覽器的問題幾乎與手機(jī)瀏覽器中的問題如出一轍。不同版本的手機(jī)瀏覽

7、器也是多得驚人。 每個設(shè)備制造商都擁有各自的瀏覽器,甚至來自相同廠商的設(shè)備在操作系統(tǒng)、屏幕大小等方面都有很大的差別。 有些瀏覽器只支持 WAP,而有一些則支持部分的 HTML,還有一些完全支持 HTML,但不支持 JavaScript。 幸好,現(xiàn)在情況已經(jīng)大不相同了。到 2010 年 1 月,美國有超過 80% 的移動互聯(lián)網(wǎng)流量都是通過 iPhone 或 Android 手機(jī)產(chǎn)生的。這兩種操作系統(tǒng)不僅都是使用 WebKit 進(jìn)行 HT

8、ML/CSS 渲染, 而且它們都是一樣積極地使用 HTML 5 標(biāo)準(zhǔn)所采用的 JavaScript 引擎。沒錯。 移動領(lǐng)域的主流瀏覽器現(xiàn)在都使用了開放標(biāo)準(zhǔn)。這是 Web 開發(fā)人員所遇到的最好時機(jī)。,,瀏覽器之間還是存在差別的,即使是不同版本的 iPhone 和 Android 也不例外。 其中 Android 瀏覽器差別最大。在 2.0 之前版本的 Android 上,Android 瀏覽器使用的是私有的 Google Gears 技術(shù)

9、。雖然 Gears 有很多優(yōu)秀的創(chuàng)新技術(shù),現(xiàn)在已經(jīng)包含在 HTML 5 標(biāo)準(zhǔn)中了。 然而,這意味著在很長的一段時間里,Android 瀏覽器是不支持其中一些 HTML 5 標(biāo)準(zhǔn)的, 但是我們還是能夠使用 Gears 來實(shí)現(xiàn)一部分功能。本文的所有代碼都是基于 HTML 5 標(biāo)準(zhǔn)并且是可以正常運(yùn)行在 Android 2.0+ 或 iPhone 3.0+ 上的。 既然我們已經(jīng)擁有了這些現(xiàn)代的基于 WebKit 的瀏覽器,接下來讓我們來看看一些

10、這些設(shè)備上的 Ajax。,手機(jī)瀏覽器上的 Ajax,像桌面 Web 應(yīng)用一樣,在移動 Web 應(yīng)用上創(chuàng)建引人注目的用戶體驗(yàn)的關(guān)鍵通常就是使用 Ajax。當(dāng)然, 用戶體驗(yàn)并不是使用 Ajax 的唯一原因;其中還可能涉及到速度和效率的原因。而后者恰恰是在移動 Web 應(yīng)用上使用 Ajax 的更重要的原因所在,因?yàn)橐苿泳W(wǎng)絡(luò)的延遲更大,而瀏覽器本身也受到處理器速度、 內(nèi)存和緩存大小的限制。幸好,由于只需要關(guān)注于基于標(biāo)準(zhǔn)的瀏覽器,因此 Ajax

11、則恰好是許多因此變得更簡單的技術(shù)之一。在詳細(xì)討論這個問題之前, 讓我們先快速地了解一下本文所開發(fā)的應(yīng)用所使用的后臺服務(wù)器。 在開始之前,我們需要下載必要的 JAR 文件,其中包括 Jersey、Xerces、Rome 和 Google App Engine SDK 。然后將它們安裝到下面的文件夾中:WebKitBlog>war>WEB-INF>lib。,WebKit 博客,本文的移動 Web 應(yīng)用是一個簡單的閱讀移動

12、 Web 開發(fā)新聞的應(yīng)用。雖然目前它只是簡單地從官方 WebKit 博客抓取 RSS 源,但是它可以經(jīng)過簡單地修改來收集多個 RSS 源。這個應(yīng)用是一個普通的 Java Web 應(yīng)用,它可以部署到任何一個 Java 應(yīng)用服務(wù)器上。所有代碼見清單 1。,清單 1. Feed 類,@Path("/feed")public class Feed { String surfinSafari = "http

13、://webkit.org/blog/feed/"; @GET @Produces("application/json") public News getNews(@DefaultValue("0") @QueryParam("after") long after) throws Exception{ URL feedU

14、rl = new URL(surfinSafari); SyndFeedInput input = new SyndFeedInput(); SyndFeed feed = input.build(new XmlReader(feedUrl)); List entries = new ArrayList(feed.getEntries().size()); for (Objec

15、t obj : feed.getEntries()){ SyndEntry entry = (SyndEntry) obj; if (entry.getPublishedDate().getTime() > after){ Item item = new Item(entry.getTitle(), entry.getLink(),

16、 entry.getDescription().getValue(), entry.getPublishedDate().getTime()); entries.add(item); } } return new News(feed.getTitle(),

17、 entries); }},,這個類使用 Java 的 JAX-RS 創(chuàng)建一個 RESTful 服務(wù)。@Path 注釋表示了服務(wù)的終端,即服務(wù)的相對 URL 是 /feed。@GET 表示這個服務(wù)支持 HTTP GET。@Produces 聲明這個服務(wù)將生成 JSON 格式的數(shù)據(jù)。這是一個簡單的以 JSON 格式序列化數(shù)據(jù)的方法。 方法 getNews 接收一個名為 after 的參數(shù), 即獲取一個特定日期之后的實(shí)體。這里也使

18、用 JAX-RS 注釋來將參數(shù) after 綁定到查詢字符參數(shù) after 上。如果沒有賦值,它會使用默認(rèn)值 0。 到這里,我只闡述了 清單 1 中創(chuàng)建服務(wù)尋址和數(shù)據(jù)序列化的代碼所用到的 JAX-RS 注釋。該方法的主體實(shí)際上大部分依賴于處理 RSS 的 Rome 包。它只是下載最新的 RSS 源, 然后將它轉(zhuǎn)換成我們應(yīng)用所需要的數(shù)據(jù),這里的數(shù)據(jù)就是 Item 和 News 這兩類。其中唯一復(fù)雜的部分是文章的發(fā)表日期被轉(zhuǎn)化為一個 lo

19、ng 值,并用作一個 ID。這是一個非常有用的 ID, 因?yàn)槲覀兛梢杂盟鼇磉M(jìn)行排序,我們將在后面使用到。News 類如清單 2 所示。,清單 2. News 類,@XmlRootElementpublic class News { private String title; private List entries; // constructors, getters/setters omitted for br

20、evity} 注意 News 類使用了 JAXB 注釋 @XmlRootElement。 這個應(yīng)用中不使用 XML,但是 JAX-RS 使用 JAXB 完成自動的序列化/反序列化。這個類只有一個標(biāo)題屬性和一組 Item。 Item 類如清單 3 所示。,清單 3. Item 類,@XmlTypepublic class Item { private String title; private Strin

21、g link; private String description; private Long id; // constructors, getters/setters omitted for brevity} 這個類包含的就是我們在 Web 應(yīng)用中顯示的內(nèi)容。類似于 News 類, 它也使用 JAXB 注釋,這樣 JAX-RS 可以將它序列化成 JSON。這部分代碼的最后一部分是配置 Web

22、應(yīng)用的,以使請求能指向 JAX-RS。為了達(dá)到這個目的,我們需要編輯應(yīng)用的 web.xml 文件, 如清單 4 所示。,清單 4. web.xml 配置文件, WebKit Blog Servlet com.sun.jersey.spi.container.servlet.ServletContainer com.sun.jersey.config.

23、property.packages org.developerworks.mobile 1 WebKit Blog Servlet /resources/* ,,30 index.html mf text/cach

24、e-manifest 這是最典型的 web.xml 代碼。我們可以看到 servlet 聲明,應(yīng)用使用了 JAX-RS 的參考實(shí)現(xiàn) Jersey。 Servlet 的初始化參數(shù)指示 Jersey 掃描 org.developerworks.mobile 包中被標(biāo)記為處理服務(wù)請求的類。同時,任何映射到 /resources/ 的請求都將映射到 Jersey servlet。 這里最后需要注意的是文件最后的 mime-mappin

25、g 部分。這是 MANIFEST 文件的 MIME 類型, 也是我后面將討論到的脫機(jī) Web 應(yīng)用的一個關(guān)鍵。既然我們已經(jīng)了解了 Web 應(yīng)用將使用到的后臺服務(wù), 接下來我們將了解它使用到的前臺。,Ajax 構(gòu)建的用戶接口,清單 4 中我們可以看到應(yīng)用有一個標(biāo)準(zhǔn)的 index.html 文件。這是應(yīng)用的入口點(diǎn),如清單 5 所示。,清單 5. index.html 文件,  WebKit News

26、 Recent News About WebKit ,,這是一個非常簡單的 Web 頁面,但是其中有許多值得注意的方面。首先,在文件頭部我設(shè)置了視區(qū)。 它指示瀏覽器放大內(nèi)容,使內(nèi)容在設(shè)備上良好顯示。在 UI 代碼方面,這里只有一個標(biāo)題和表示正在加載的圖片。 剩下的部分就是 JavaScript。文件 index.js 中的 loadEntries 函數(shù)會發(fā)送一個 Ajax 請求加載數(shù)據(jù)。這個函數(shù)

27、如清單 6 所示。,清單 6. loadEntries 函數(shù),function loadEntries(){ if (!window.JSON){ var head = document.getElementsByTagName("head")[0]; var jsScript = document.createElement("script");

28、 jsScript.setAttribute("src", "json2.js"); jsScript.setAttribute("type","text/javascript"); head.appendChild(jsScript); } var xhr = new XMLHttpRequ

29、est(); xhr.onreadystatechange = function(){ if (this.readyState == 4 &&this.status == 200){ var theFeed = JSON.parse(this.responseText); var i = 0;,,if (theFeed.ent

30、ries){ var len = theFeed.entries.length; for (i=0;i<len;i++){ addEntry(theFeed.entries[len - 1 -i], true); }

31、 } var body = document.getElementsByTagName("body")[0]; body.removeChild($("loader")); } }; var urlStr = "/resources/feed

32、"; xhr.open("GET", urlStr); xhr.send(); },,,在這個函數(shù)的開始部分,我進(jìn)行了一些功能檢查。大多數(shù)瀏覽器支持內(nèi)置的解析和序列化 JSON 的函數(shù)。 這與 json.org 上的 JSON 庫是相同的。然而,如果沒有這個函數(shù),我們需要在頁面上包含這個文件, 然后我們就有相同的功能了。 另外,這是非常簡單的 Ajax 代碼。我們不需要擔(dān)心

33、 Internet Explorer 不支持,所以我們可以直接創(chuàng)建一個 XMLHttpRequest。我們可以設(shè)置它的 onreadystatechange 屬性為一個函數(shù),在本例中將創(chuàng)建一個閉包。當(dāng)響應(yīng)從服務(wù)器返回(readyState = 4)且處理過程沒有發(fā)生問題(status = 200 OK)時,我們就使用 JSON.parse 函數(shù)來解析 JSON 響應(yīng)。對于來自源的每一個記錄執(zhí)行 addEntry 函數(shù)。 這個函數(shù)為每一個

34、記錄創(chuàng)建 UI 元素。如清單 7 所示。,清單 7. addEntry 函數(shù),function addEntry(e, prepend){ var eDiv = document.createElement("div"); eDiv.setAttribute("class", "item"); var link = document.createElem

35、ent("a"); link.setAttribute("href", e["link"]); var title = document.createTextNode(e["title"]); link.appendChild(title); eDiv.appendChild(link); var button = d

36、ocument.createElement("input"); button.setAttribute("type", "button"); button.setAttribute("value", "Show"); button.setAttribute("id", "button&

37、quot; + e["id"]); button.setAttribute("onclick", "showDescription('" + e["id"] + "')");,,eDiv.appendChild(button); var dDiv = document.createElement("

38、;div"); dDiv.setAttribute("id", e["id"]); dDiv.setAttribute("class", "description"); dDiv.setAttribute("style", "display:none"); dDiv.inner

39、HTML = e["description"]; eDiv.appendChild(dDiv); var body = document.getElementsByTagName("body")[0]; if (!prepend && body.childNodes.length > 1){ body.appendChild(e

40、Div); } else { body.insertBefore(eDiv, body.childNodes.item(2)); }},,這個函數(shù)里執(zhí)行的都是標(biāo)準(zhǔn)的 DOM 操作。唯一復(fù)雜的方面是記錄可以附加在后面或插到前面, 或者添加到頂部或底部。在前面的 清單 6 中,函數(shù)的最后一個操作是刪除正在加載的圖片。 這其中包括基本的 Ajax 函數(shù),我們可以根據(jù)用例選擇使用。然而,應(yīng)用需要從服務(wù)器

41、下載許多數(shù)據(jù), 然后再解析。對于移動 Web 應(yīng)用,我們可以有更好的方式,我們可以使用本地緩存。 使用本地存儲進(jìn)行緩存本地存儲屬于 HTML 5 規(guī)范,并且得到廣泛的支持。它有一個簡單的 name - value 存儲機(jī)制, 而其中 name 和 value 都是字符串。所以將記錄保存到本地存儲是很簡單的,如清單 8 所示。,清單 8. 保存到本地存儲,function saveLocal(entry){ if (!wind

42、ow.localStorage){ return; } localStorage.setItem(entry["id"], JSON.stringify(entry));} 同樣,這里做了一些瀏覽器功能檢查,按照 HTML 5 規(guī)范,首先檢查 window 對象是否有 localStorage 屬性。 如果有,那么我們就可以使用記錄的 id 作為存儲的鍵。 對于 val

43、ue,必須使用字符串,因此我們使用 JSON.stringify 函數(shù)來將對象序列化成一個字符串。 這樣,我們只需要一個從本地存儲讀取所有數(shù)據(jù)的函數(shù)。如清單 9 所示。,清單 9. 從本地存儲加載數(shù)據(jù),function loadLocal(){ if (!window.localStorage){ return []; } var i = 0; var e = {}; var id

44、 = 0; var entries = []; for (i=0; i< localStorage.length; i++){ id = localStorage.key(i); e = JSON.parse(localStorage.getItem(id)); entries[entries.length] = e; } entries.sort(f

45、unction(a,b) { return b.id - a.id; }); return entries;},,同樣,這個函數(shù)從檢查本地存儲是否可用開始。接著,它遍歷本地存儲中的所有數(shù)據(jù)。 對于存儲中的每一個值,我們再次使用 JSON.parse 函數(shù)來將字符串解析成為一個對象。 接著,我們需要對記錄進(jìn)行排序,因?yàn)樗鼈儚谋镜卮鎯Ψ祷氐捻樞蚴遣灰欢ǖ?。這里進(jìn)行了一個降序排序,最新記錄在最前面。 最后

46、,我們就有了本地存儲的保存和加載函數(shù),我們需要將它們整合到 loadEntries 函數(shù)中, 如清單 10 所示。,清單 10. 添加緩存到 loadEntries 函數(shù),function loadEntries(){ // check for JSON object var localEntries = loadLocal(); var newest = 0; if (localEntries.leng

47、th > 0){ newest = localEntries[0].id; } var i = 0; for (i=0;i<localEntries.length;i++){ addEntry(localEntries[i]); } var xhr = new XMLHttpRequest(); xhr.onreadystatechange =

48、function(){ if (this.readyState == 4 && this.status == 200){ var theFeed = JSON.parse(this.responseText); var i = 0; if (theFeed.entries){

49、 var len = theFeed.entries.length; for (i=0;i<len;i++){ addEntry(theFeed.entries[len - 1 -i], true);,,saveLocal(theFeed.entries[len - 1 -i]);

50、 } } var body = document.getElementsByTagName("body")[0]; body.removeChild($("loader")); } }; var urlStr

51、= "/resources/feed?after=" + newest; xhr.open("GET", urlStr); xhr.send(); } 這里的主要區(qū)別是我們首先加載本地?cái)?shù)據(jù)。接著確定其中最新的記錄,然后在我們連接服務(wù)器時使用這個參數(shù), 服務(wù)器將只會返回不在本地存儲的記錄。最后,當(dāng)我獲得新的記錄后,在回調(diào)函數(shù)中我們需要調(diào)用 saveLocal 函

溫馨提示

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

評論

0/150

提交評論