Android Weekly Notes Issue #233

Android Weekly Issue #233

November 27th, 2016
Android Weekly Issue #233
本期內容包括: 用Mockito做RxJava的單元測試; Android開發中的命令行使用; Android 7.1的App Shortcuts; 自定義View的繪制; 用Firebase的Remote Config進行feature逐步分發; APK分析工具的使用, APK瘦身討論; RxJava處理網絡請求和緩存; presenter的設計; 用Firebase發送push notification; transient關鍵字的使用等.

ARTICLES & TUTORIALS

Testing asynchronous RxJava code using Mockito

這篇文章講了如何用Mockito給RxJava的異步請求代碼寫單元測試.
內容包括了:

  • 如何設置Mockito的默認返回值. (通過自定義的MockitoConfiguration類).
  • 如何把異步變為同步測試. (1.用blockingGet(); 2.在RxJava2中, 可以使用TestObserverawaitTerminalEvent()).
  • AssertJ的使用.
  • 測試異步代碼. 使用Rule來替換原來的scheduler.
  • flatMap(), concatMap(), concatMapEager()操作符的使用.
  • 測試Timeout.
  • 測試異常和retry邏輯.

好用的工具: AssertJ
用來更方便地寫Java測試中的assert語句.

Mastering the Terminal side of Android development

作者分享了在Android開發中他是如何使用命令行的.

使用更好的命令行程序: iTerm2.
它有很多有用的features, 比如分屏, 自定義顏色, 粘貼歷史等.

on-my-zsh:

on-my-zsh內置了一個git plugin, 提供了很多aliases和功能.

zsh-autosuggestions會在你輸入的時候根據歷史提供建議.

你可以用Ctrl + R在命令歷史中進行逆向智能搜索(Reverse intelligent search). 你開始輸入這個命令, 命令行會在歷史中尋找并自動補全. 你可以按Enter來執行這個命令, 或者左右箭頭來編輯命令, 或者繼續按Ctrl + R在其他可能的命令中尋找.

dryrun

如果你在github上看到一個程序, 想要運行一下看看, 你不必再把它下載下來, 導入Android Studio了.

你只需要用dryrun, 一句命令就可以:

dryrun REMOTE_GIT_URL

Build faster, build offline

在build的時候使用--offline可以讓所有依賴都使用緩存版本, 不再進行網絡請求, 從而加快執行速度.

./gradlew assembleDevelopDebug --offline
./gradlew test --offline

在Android Studio中也可以進行設置.
Settings -> Build, Execution, Deployment -> Build tools -> Gradle中勾選Offline work即可.

alfi
alfi是一個工具, 裝了這個工具之后, 用一行命令就可以查到第三方庫的依賴語句, 然后你就可以把它拷貝粘貼到build.gradle中去了.

gradle tasks shortcuts
gradle的task有縮寫版的, 比如:

  • iDD for installDevelopmentDebug
  • aDD for assembleDevelopmentDebug
  • cC for connectedCheck

Android Rocket Launcher
Android Rocket Launcher增加新的tasks, 在命令行啟動應用.

直接在console輸出單元測試結果:

android {
  ...
  testOptions.unitTests.all {
    testLogging {
      events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
      outputs.upToDateWhen { false }
      showStandardStreams = true
    }
  }
}

這個工具pidcat可以指定包名顯示log.

Exploring Android Nougat 7.1 App Shortcuts

這篇文章講Android 7.1推出的App Shortcuts如何實現.

The Quirks of Supporting SDK 25

作者分享了她在適配Nougat, API 25時學到的東西, 包括更換SDK版本, 圓形的啟動icon, 還有app shortcuts. (根據文中的圖標, 這個app居然是domain).

Android: draw a custom view

作者自定義了一個ViewPager的page indicator: PageIndicatorView.

這篇文章講述了如何自定義View, 首先是View的生命周期, 然后是具體如何實現, 如何避免一些常見的錯誤, 最后是如何添加View的動畫.

view-lifecycle.png

各個生命周期中應該干的事情:

  • 構造函數中: 解析自定義屬性.
  • onAttachedToWindow()中: 可以發現同一布局中相關的其他View, 其id是上一步通過自定義屬性傳入的.
  • onMeasure(): 自定義View尺寸相關, 當覆蓋這個方法時, 最后要調用setMeasuredDimension(int width, int height).
  • onLayout(): 一般這個方法是給ViewGroup的child指定位置和尺寸的, 對于自定義View來說, 沒有child就沒有必要覆蓋這個方法.
  • onDraw(): 這里是畫東西的地方. 用canvas和Paint結合繪制. 需要注意的是onDraw()會被多次調用, 當你有一些變化, 滾動滑動等, 都會重繪, 所以這個方法中不要創建新對象.

View更新
有兩個方法可以讓View重繪:

  • invalidate(): 只是重新繪制, 調用onDraw()方法.
  • requestLayout(): 將會從onMeasure()開始, 可能會改變尺寸, 然后根據新尺寸重新繪制.

Animation
自定義View的動畫是一幀幀進行的, 這就意味著你每一步都要調用invalidate()來畫它.

在自定義View中你的動畫好助手是ValueAnimator, 它可以讓你動畫任何值.

How to Stage Rollout Features using Firebase Remote Config

Staged Rollout是Google Play Store的一個feature. 讓你可以慢慢地把新版App發布給一部分用戶, 并逐漸增大比例. 使用Firebase Remote Config, 我們可以做的更多, 我們可以控制某個feature的發布.

Making the most of the APK analyzer

Android Studio中Build菜單有一項是Analyze APK..., 這是一個很有用的功能.

Raw File Size是apk在磁盤上的大小.
Download size是估計下載你的應用所需要的數據流量大小, 考慮到了Play Store的壓縮.

文件和文件夾是按照大小降序排列的. 這對于Apk瘦身來說很有用, 很容易發現最占地方的原因.

比如作者發現了一些png很占地方, 于是就用PSD support in the Vector Asset import tool把它們轉成了VectorDrawable, 后向兼容用VectorDrawableCompat.

有一些沒有壓縮的WAV可以轉成OGG.

在lib/里面, 發現它們要支持的三個ABI: x86, armeabi-v7a, armeabi, 解決的辦法就是利用apk拆分, 針對每一個ABI有一個不同的版本.

還有一個優化是把android:extractNativeLibs 屬性設置為false, 這樣系統就不會把.so文件在安裝的時候從apk中拷貝到文件系統了. 這樣應用的增量更新也會小一點.

這個功能有一個"Compare with"按鈕, 利用它你可以比較兩個apk的改變.

可以通過查看DEX文件來查看方法數限制 (Referenced Methods), 類混淆等問題.

Rxify : The Anti Cache-then-Network OR Network-then-Cache Problem

用RxJava處理網絡請求和緩存.

  • 如果先使用Cache, 沒有緩存的時候再進行網絡請求. -> 用.concatWith().take(1).
  • 如果優先取網絡最新數據, 沒網的時候才用緩存數據. -> .onErrorReturn().

Your presenters don’t need all those lifecycle events

作者認為在Presenter中放入太多生命周期的方法不太好, 他覺得最基本的只需要這兩個方法:

public interface Presenter {
  void onViewAttached(MVPView view); 
  void onViewDetached();
}

當然當你需要更多的時候可以加入更多, 但是我們不應該每個生命周期方法都加進去.

How to send notifications using Android Firebase

使用Firebase Messaging如何發送push notification.

RxRecipes: Wrap your way to Rx

使用.fromCallable()來把一個同步方法包裝成一個Observable.

并比較了和.just()的區別. (.just()發射的東西在創建的時候就確定了, 而.fromCallable()是在subscribe的時候確定的.)

Diving deeper into the Java transient modifier

transient修飾符加在字段上時, 在對象被序列化的時候, 這個字段將被排除在外, 反序列化時這個字段將被初始化一個默認值.

可能的使用場景:

  • 實現了Serializable的User對象中的password字段.
  • 一個Serializable的類中的某個字段是通過其他字段推導或派生出來的, 這些派生的字段沒有必要被序列化, 于是把它們標記為transient.

注意transient和static是不能并存的, 因為static默認是transient的.

LIBRARIES & CODE

Tinker

騰訊的熱補丁(hot-fix)解決方案, 支持不重新安裝app的dex, library和資源更新.

Android-Debug-Database

在瀏覽器里看應用的數據庫和shared preferences.

blurkit-android

實時模糊布局. 像iOS一樣.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容