Android Weekly Notes Issue #235

Android Weekly Issue #235

December 11th, 2016
Android Weekly Issue #235
本期內容包括: 開發一個自定義View併發布爲開源庫的完整流程介紹; 用AnimatedVectorDrawable實現的動畫; 什麼樣的程序是可測試的; DownloadManager介紹; Okhttp的重試; Android 7取消了file://; Android Studio即將推出的build cache功能; 支持離線模式的app構架; 如何寫自定義的lint規則; Epoxy, 一個處理複雜RecyclerView屏的庫; FragmentPagerAdapterFragmentStatePagerAdapter的比較等.html

ARTICLES & TUTORIALS

Make an android custom view, publish and open source

做者開發了一個環形的SeekBar, 並把它做爲一個庫發佈到了JCenter.java

做者首先講了自定義View的實現:
首先是關於View生命週期的介紹, 在寫自定義View的時候有幾個關鍵的生命週期回調須要處理:
view-lifecycle-diagram-lite-versionandroid

做者實現的幾個關鍵步驟講解:git

  • 自定義屬性並獲取.
  • onMeasure()中控制尺寸.
  • onDraw()中繪製: 避免在onDraw()中分配內存; 用invalidate()方法來激發重繪.
  • onTouchEvent()處理用戶手勢. 在他的環形SeekBar的實現裏, 這裏涉及到了點擊座標到角度的轉換.

將自定義View庫開源到Github:
開源到Github有個好的README很重要, 這裏有幾個tips:github

  • 提供截圖, Gif或者Video.
  • 提供安裝/使用說明.
    做者本身的庫: SwagPoints

發佈庫:api

  • JFrog Bintray註冊.
  • 建立repository, package, 和版本號.
  • 生成並上傳, 用了這個library.
  • 添加到Jcenter.
  • 被接受以後收到郵件, 就可使用了.

Animation: Jump-through

AnimatedVectorDrawable實現的一個很fancy的位置標誌動畫.android-studio

What makes Android Apps Testable

若是程序的架構不適合測試, 那麼硬要寫一些測試極可能就會面臨這樣的局面: 要麼就是發現無法寫測試, 要麼就是爲了寫測試而破壞了代碼, 作了一些奇怪的事情.緩存

那麼究竟是什麼樣的程序纔是適合寫測試, 或者是可測試的呢?cookie

有一個有趣的定義是seam(接縫), 在接縫處你能夠改變程序的行爲, 而不用編輯當前程序. 若是程序沒有接縫, 你將沒法設置測試的初始條件和驗證測試結果.網絡

本文中舉了一個實際的例子, 開始的時候程序沒有seam, 因此致使沒法測試, 後來把靜態方法改成實例的方法以後, 咱們就能夠經過Mockito來模擬行爲, 設置條件, 最後經過驗證某一方法的調用與否來進行驗證.

DownloadManager – Part 3

DownloadManager來處理下載.
首先它在設備上有本身的UI, 還有notification, 還有Downloads app能讓用戶管理下載文件.

咱們能夠查詢到文件的一些信息, 好比MIME type, 文件尺寸, 下載狀態等.

咱們還能夠用getUriForDownloadedFile()方法來獲取一個URI, 配合MIME type, 發送Intent, 來打開一個相關的查看程序.

關於儲存文件的合適地點:

  • 文件小, 僅app本身使用 -> 私有數據區域(默認行爲).
  • 文件大, 僅app本身使用 -> 外部存儲的私有數據區域(不須要權限). setDestinationInExternalFilesDir().
  • 文件須要被別的應用訪問 -> 外部存儲的共有區域, 須要WRITE_EXTERNAL_STORAGE權限. setDestinationInExternalPublicDir().

OkHttp is quietly retrying requests. Is your API ready?

在網路較慢或不穩定的時候, OkHttp有可能會重複發送請求, 直到成功.

這個重試的邏輯是經過RetryAndFollowUpInterceptor.java實現的.

那麼, 咱們能夠關掉這個重試行爲嗎? 有一些issues就在討論這個問題: Issue # 1043. 後來有兩個pull requests: PR #1259PR #2479改進了這個問題, 減小(但並無消除)了沒必要要的retry請求.

全局關閉重試行爲: OkHttpClient.Builder .retryOnConnectionFailure()設置爲false. 可是注意這樣是很粗暴並具備破壞性的, 消除了retry邏輯帶來的好處:

  • 若是Url有多個IP, 失敗了一個還能夠試另外一個.
  • 鏈接池中的鏈接偶爾會time out, 減小這種意外致使的後果.
  • 能夠順次查找多個代理, 若是都失敗了再轉向直接鏈接.

解決真正的問題: 關閉靜默重試在某些情形下有幫助, 可是其實它隱藏了真正的問題, 就是你的API是不是冪等的idempotent. server端能夠根據客戶端的GUID來檢測重複, 這樣server就不會屢次執行操做, 會通知發送者.

File scheme is now not allowed with Intent on N

Android N (Nougat, API 24)開始, 再也不容許發送file://的Intent, 將會直接拋出FileUriExposedException異常.

因此當你把targetSdkVersion改成24以後, 你必需要確保你修復了這些問題再發布.

解決方案是什麼呢? 用content://, 結合FileProvider:
首先在manifest裏面聲明:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

而後在res\xml\provider_paths.xml文件裏指明路徑:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

最後, 把

Uri photoURI = Uri.fromFile(createImageFile());

改成

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
        BuildConfig.APPLICATION_ID + ".provider",
        createImageFile());

而後放在Intent裏發送就行了.

注意, 若是你的targetSdkVersion尚未更新到24, 那麼即使是在Nougat的手機上file://也仍然是能正常使用的.

Use Android Studio Gradle Build Cache for faster builds

Android Studio當前的最新版是2.3 Canary 2. 有一些新的改進, 可是其中最吸引人的是這個build cache. 它會使你的clean build更快.

本文後面解析了build cache的工做原理.

Offline App Architecture, build for the Next Billion

一個好的應用應該在網絡很差甚至離線的時候仍然可使用, 咱們應該作些什麼呢?

  • 肯定鏈接情況. 可使用這個network-connection-class. 若是你使用的是Okhttp, 能夠加一個Intercepter來進行採樣.
  • 有效地緩存. 從網絡取數據很慢而且昂貴, 因此有效地利用以前取到的數據是很關鍵的優化. (Cache-Control, Etag).
  • 在本地操做, 在全局同步. 等網絡請求的時候能夠先顯示本地數據, 而不是loading.
  • 有效地處理線程.
  • 優化圖片. 網絡很差的時候先用RGB_565, 等網絡變好了再取高質量圖片.
  • 使用大Cookie. 儘可能一次傳輸更多的數據(big cookie), 而不是頻繁發送一些小請求(small cookies).

Writing custom lint rules and integrating them

如何建立自定義的lint規則.
事情的由來是做者發現了一個死循環調用, 而後他想作一個什麼標記以防之後其餘人會犯一樣的錯誤.

而後他想到的是@Nullable註解, 的檢查, 實質是依靠lint來實現的.

因而他本身寫了一個自定義的lint規則, 來提示使用用他的註解@CarefulNow標記的方法時應當注意.
詳細的實現方式請看原文.

Epoxy: Airbnb’s View Architecture on Android

epoxy是一個Android庫, 用來處理複雜的RecyclerView屏. 本文介紹了它在項目中實際的使用.

Adventures with FragmentStatePagerAdapter

可能有不少Android開發者對於
FragmentPagerAdapterFragmentStatePagerAdapter的區別不是太清楚或根本不知道, 本文做者就具體介紹了兩者的不一樣.

基本不一樣

FragmentPagerAdapter
適用於項目個數肯定的情形.
爲何呢? 由於一旦fragment的實例被建立, 它永遠也不會從FragmentManager中移除, 直到Activity被銷燬.

當Fragment不見的時候, 僅僅是onDestroyView()被調用, 當fragment再次回來時, 再調用onCreateView().

FragmentStatePagerAdapter
當fragment的實例不可達的時候, 實例就會當即從FragmentManager移除. 被移除的fragment實例的狀態由FragmentStatePagerAdapter保存, 當你再次回到該項的時候, fragment會重建新實例, 而且狀態被恢復. 因此這種adapter適用於項目個數不肯定或的狀況.

因此使用FragmentPagerAdapter的時候須要注意內存問題.

notifyDatasetChanged()的問題.

notifyDataSetChanged()是用來處理數據集變化的狀況, 好比一些項目增刪的狀況. 這個方法不是用來刷新當前顯示的Fragment或其中的Views的.

文章中還有一些關於數據改變實現以及現有issue的討論. 爲了解決issue做者還發布了一個庫UpdatableFragmentStatePagerAdapter.

LIBRARIES & CODE

KeepActivitiesTile

一個quick settings tile來開啓"Don't keep activities".

WaveLoading

一個波形的loading圖, 水面上漲表明loading程度.

coordinators

Simple MVWhatever for Android.

epoxy

一個處理複雜的RecyclerView屏的庫.

Screen Record for Android

錄屏腳本.

相關文章
相關標籤/搜索