Android-入門學習筆記-線程與並行

3html

"你感受到了嗎?" 應用的 GitHub Repo 地址.java

6node

Android 系統可以同時運行多個線程, 所以能夠相互獨立的處理 兩組或多組任務。若是有多個線程須要運行, Android 還會就什麼時候運行哪些線程進行優先級排序, 並肯定各線程的運行時長。react

線程也知道如何保存其位置。它不只會記錄全部變量的值, 還會記住完成當前正在執行的指令 會調用的函數系列: 即可以從新完成工做所需的一切內容。android

構建全部多線程應用程序都是爲了可以同時運行兩個或 多個進程。現代編程語言和 CPU 旨在利用多線程, 所以,在 Android 平臺上構建應用並無什麼不一樣!git

有關更進一步的討論,請參閱「進程與線程」這篇文章github

還有另外一篇關於「保持你的應用及時響應」這一話題的開發者指南編程

7json

我強烈建議觀看關於線程的 Android Performance Patterns Youtube視頻,演講者爲 Google 技術推廣工程師 Colt McAnlis。數組

 8

設計提示:理論上,應用中的內容是即時加載的。若是 未加載,請嘗試容許用戶與應用的其餘部分進行交互, 以便用戶不會坐在那裏無所事事,或是觀看進度條。若是應用中沒有 任何有意義的事可供用戶去作,材料設計規範提供了有關如何針對須要花費很長時間加載的內容來 顯示進度的指南。

 10

AsyncTask 文檔

使用 AsyncTask 進行後臺處理

 11

要檢查 NetworkConnect 應用,能夠從開發者站點下載代碼。或者 在 Android Studio 內,單擊文件 (File) > 新建 (New) > 導入示例 (Import Sample),並搜索 "Network Connect" 示例。

內部類

12

提示:若是你陷入僵局,須要更詳細的步驟,請參閱此 列表。可是,首先要嘗試本身完成任務!

  1. 建立 AsyncTask 的子類做爲 MainActivity 類中的 私有內部類。 實現 doInBackground() 方法來獲取地震數據並 返回結果。 實現 onPostExecute() 方法以根據咱們的結果 更新 UI。

  2. 在 MainActivity onCreate() 方法中建立咱們的內部類的實例, 並執行。

 13

我要指出的是,目前,咱們的代碼是針對最佳 狀況編寫的。咱們假設 EarthquakeAsyncTask 經過咱們預期的輸入調用, 且在執行網絡請求時未出現任何 錯誤。

若是…

  • 將來使用此應用的隊友更改了代碼,並試圖以不輸入任何參數的方式來執行 EarthquakeAsyncTask,這將如何?咱們的應用可能會崩潰,由於它假設至少爲任務輸入 1 個字符串。
  • USGS 的計算機存在內部服務器錯誤,沒法將響應解析爲 Event 對象,這又將如何?咱們的應用將嘗試使用無效或空 Event 對象更新 UI。

咱們試圖進一步驗證咱們的應用,以便咱們或接觸代碼的任何其餘開發者 不會不當心在應用中致使 bug 或崩潰。 爲此,咱們須要將當前類之外的代碼編寫假設、 以及超出咱們控制的假設 最小化。

若是咱們能夠接受任何輸入(零輸入、1 個 輸入、2 個輸入等)或處理任何意外行爲(服務器 作出有效或無效響應),並作出得體的處理而不使應用崩潰, 那麼就說明咱們的代碼變得更加穩健。

爲了這個目的,請對 "你感受到了嗎?" 應用進行下列修改, 以處理 EarthquakeAsyncTask 中空或 Null 狀況。

在 doInBackground 方法中,檢查 url 數組是否至少具備 1 個 條目且第一個條目不爲空。若是數組長度爲 0 或第一個條目爲空,則經過返回 null 提前離開 此方法。咱們須要返回 null,由於須要有對象 做爲返回值。若是有 1 個有效字符串 URL,則繼續 獲取數據。

protected Event doInBackground(String... urls) { // 若是不存在任何 URL 或第一個 URL 爲空,切勿執行請求。 if (urls.length < 1 || urls[0] == null) { return null; } Event result = Utils.fetchEarthquakeData(urls[0]); return result; } 

在 onPostExecute 方法中,若是不存在地震結果,則提前 返回。

protected void onPostExecute(Event result) { // 若是不存在任何結果,則不執行任何操做。 if (result == null) { return; } updateUi(result); } 

下面是完整的 EarthquakeAsyncTask 類聲明。

/** * {@link AsyncTask} 用於在後臺線程上執行網絡請求,而後 * 使用響應中的第一個地震更新 UI。 */ private class EarthquakeAsyncTask extends AsyncTask<String, Void, Event> { /** * 此方法在後臺線程上激活(調用),所以咱們能夠執行 * 諸如作出網絡請求等長時間運行操做。 * * 由於不能從後臺線程更新 UI,因此咱們僅返回 * {@link Event} 對象做爲結果。 */ protected Event doInBackground(String... urls) { // 若是不存在任何 URL 或第一個 URL 爲空,切勿執行請求。 if (urls.length < 1 || urls[0] == null) { return null; } Event result = Utils.fetchEarthquakeData(urls[0]); return result; } /** * 此方法是在完成後臺工做後,在主 UI 線程上 * 激活的。 * * 能夠在此方法內修改 UI。咱們獲得 {@link Event} 對象 * (該對象從 doInBackground() 方法返回),並更新屏幕上的視圖。 */ protected void onPostExecute(Event result) { // 若是不存在任何結果,則不執行任何操做。 if (result == null) { return; } updateUi(result); } } 

你編譯並運行應用時,應該看起來是這樣的。

 
 

要在 GitHub 上瀏覽「你感受到了嗎?」應用的完整和最終狀態, 請單擊此處

15

因此最近咱們看到 List 與 ArrayList 的大量使用。它們 兩者的使用方式看起來類似,但此處 有何區別呢?

這裏的根本區別很簡單:List 是 接口,而 ArrayList 是具體類。沒法建立 List 的對象實例,由於它是接口 且其方法未實現。可是能夠建立 ArrayList 的對象實例併爲 E 指定泛型參數, 由於它是具體類。

例如:要使用 Earthquake 數據類型定義 ArrayList 的實例, 能夠編寫:

ArrayList<Earthquake> earthquakeList = new ArrayList<Earthquake>(); 

這將會運行良好。你也能夠 在 List 數據類型的變量中存儲該對象:

List<Earthquake> earthquakeList = new ArrayList<Earthquake>(); 

這樣作的緣由是爲了具備更大的靈活性:

與 ArrayList 類類似的另外一種類型的類是 LinkedList,此類 也可用於實現 List 接口。這兩種類具備類似的方法 和實現策略,但兩者內部詳細信息和存儲器 略有不一樣。若是出於某種緣由,你的應用會 因使用 LinkedList 而非 ArrayList 而從中受益,則 僅在實例的定義位置進行更新會很容易, 而且全部 List 代碼仍能正常工做!下面是一個例子:

List<Earthquake> earthquakeList = new ArrayList<Earthquake>(); earthquakeList.add(foo); 

變爲:

List<Earthquake> earthquakeList = new LinkedList<Earthquake>(); earthquakeList.add(foo); 

而且它仍能工做!

在全部狀況下,最佳的作法是,只要須要列表對象(不論是 ArrayList 仍是 LinkedList)時,便使用 List, 這樣你就能夠 保持代碼的靈活性。

要了解有關這方面的更多信息,請閱讀 List 接口的文檔, 並查看 什麼時候使用 List 和什麼時候可能使用 ArrayList 與 LinkedList 中有關 StackOverflow 的熱烈討論。

16

是時候挽起袖子開始編碼了!

修改 地震報告應用,以作出對此 URL 的網絡請求。 此查詢將爲你提供全球最近發生的震級至少爲 6 級 的 10 大地震。http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10

收到響應後,解析 JSON,而後更新 應用中的列表。

提示 #1:在進行這些增量更改時, 嘗試儘量多地編譯並運行應用。不然,最後可能會有大量錯誤 須要解決。

提示 #2:請記住,你能夠回過來參考 "Soonami" 和 "Did You Feel it" 示例應用。

若是你須要更多調試提示,請查看此論壇線程,其餘 學生會在這裏就如何完成此長編碼任務發表建議。

來自大家課程導師的備註: 上面那個 HTTP 連接,有可能會返回 301 的狀態碼,是由於請求被重定向到HTTPS了。瀏覽器一般會自動處理這個重定向,可是咱們如今的代碼請求並不會自動處理這個問題,因此把連接改爲HTTPS便可。

順便,更多關於 HTTP 狀態碼( HTTP Status Code )的介紹能夠看這裏,更多關於 HTTPS 能夠看這裏。固然去看Wikipedia的介紹也是極好的。

17

「Android 性能模式」視頻

 18

做爲提示,如下是可能的答案選項:

onLoaderReset()

onCreateLoader()

LoaderManager.LoaderCallbacks

LoaderManager

onLoadFinished()

getLoaderManager().initLoader(0, null, this);

有關詳細信息,請查看此處:

Loader 開發者指南

LoaderManager

LoaderCallbacks

19

做爲提示,如下是可能的答案選項:

AsyncTaskLoader

List

loadInBackground()

若是遇到困難,請查看如下資源:

AsyncTaskLoader 示例

Loader 開發者指南

LoaderManager

LoaderManager.LoaderCallbacks

 21

當 地震報告應用具備在整個代碼中添加的日誌消息時, 請測試如下場景:

  • 旋轉設備
  • 轉至主屏幕並返回到應用
  • 按返回按鈕
  • 打開近期任務
  • 切換到不一樣的應用
  • 返回到應用
  • 走進本身的場景!

 

22

可選:你是否瞭解嘗試將空狀態變爲 愉快用戶體驗的 Android 應用?在論壇上 分享屏幕截圖。

ListView setEmptyView() 方法。

材料設計原則 - 與空狀態有關。

 23

提示:在常見 Android 視圖備忘表中查看 ProgressBar 視圖的示例。

Material Design 進度與活動

提示:執行如下 2 個測試,檢查加載指示符 將通向地震結果列表仍是 空視圖。

測試 #1:強制後臺線程睡眠 2 秒鐘

爲強制後臺線程睡眠 2 秒鐘,咱們 暫時模擬一個極慢的網絡響應時間咱們 「假設」耗時好久來獲取響應。這 能夠較正常狀況下延長屏幕上加載下拉菜單的時間, 以便咱們查看。

在 QueryUtils.java 文件的 fetchEarthquakeData() 方法內, 將此代碼段添加到方法頂部。將方法中的 其他部分代碼保持不變。強制後臺線程 暫停執行並等待 2 秒鐘(2000 毫秒), 而後再繼續執行此方法中的其他代碼行。 若是嘗試單獨添加 Thread.sleep(2000); 方法調用, Android Studio 將告知存在未捕獲的異常,因此 咱們須要使用 try/catch 塊將該語句括起來。

在 QueryUtils.java 中:

public static List<Earthquake> fetchEarthquakeData(String requestUrl) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } … } 

如今,當運行應用時,將顯示 2 秒鐘的加載指示符, 而後纔出現地震列表。

測試 #2:假設沒有從服務器返回任何結果

在 EarthquakeActivity onLoadFInished 方法中,暫時註釋掉 向適配器添加地震數據的 代碼行。這會使應用看起來像是沒有要顯示的地震 結果。

在 QueryUtils.java 中:

@Override public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) { ... // 若是存在 {@link Earthquake} 的有效列表,則將其添加到適配器的 // 數據集。這將觸發 ListView 執行更新。 if (earthquakes != null && !earthquakes.isEmpty()) { // mAdapter.addAll(earthquakes); } } 

如今,當運行應用時,將顯示 2 秒鐘的加載指示符, 而後出現顯示「未發現地震。(No earthquakes found.)」的空狀態

24

相關文章
相關標籤/搜索