1. 程式人生 > >Android Weekly Notes Issue #226

Android Weekly Notes Issue #226

Android Weekly Issue #226

本期內容包括: 用Firebase做A/B Test; 用RxJava做動畫; MVP; proguardFiles; RxJava和Android Data Binding的結合; Mockito的更新; Gradle configurations等.

ARTICLES & TUTORIALS

作者講了如何用Firebase的Remote Config做A/B Test.

動畫基礎

它是這樣用的:

ViewCompat.animate(someButton)
    .scaleX(0f)                         // Scale to 0 horizontally
    .scaleY(0f)                         // Scale to 0 vertically
    .setDuration(300)                   // Duration of the animation in milliseconds.
    .withEndAction { removeView(view) } // Called when the animation ends successfully.

作者通過RxJava來做他們的動畫效果.
這在鏈式連線多個動畫和其他操作的時候很有用.

MVP(Model-View-Presenter)模式:

  • Model: 資料層. 負責與網路層和資料庫層的邏輯互動.
  • View: UI層. 顯示資料, 並向Presenter報告使用者行為.
  • Presenter: 從Model拿資料, 應用到UI層, 管理UI的狀態, 決定要顯示什麼以及響應使用者的行為.

V和P聯絡緊密, 所以它們通常會持有對方的引用. 為了給P做單元測試, V是一個抽象的介面. P和對應的V的關係定義在一個Contract接口裡, 這樣可以讓程式碼可讀性更好, 更容易發現二者的聯絡.

MVP模式 & RxJava在Android Architecture Blueprints裡的應用

Google blueprint的Sample是一個To Do應用. 它讓使用者可以建立, 閱讀, 更新和刪除to do task, 也可以過濾顯示. RxJava主要是用來進行一些非主執行緒的非同步操作.

然後作者詳細說明了程式碼實現.

Model中用RxJava在本地和網路取資料.
(他們的單元測試裡是下劃線和駝峰結合的方法命名方式.)

View有一個base介面:

public interface BaseView<T> {
    void setPresenter(T presenter);
}

View在onResume()的時候呼叫Presenter的subscribe(), onPause()的時候呼叫Presenter的unsubscribe(). 如果View介面的實現不是Fragment或Activity, 而是Android的自定義View, 那麼在onAttachedToWindow()onDetachedFromWindow()方法裡分別呼叫這兩個方法.

View的測試是用Espresso寫的.

Presenter也有一個base介面:

public interface BasePresenter {
    void subscribe();
    void unsubscribe();
}

View和Model都通過建構函式傳入Presenter, 在Presenter構造裡還要呼叫View的setPresetner()方法.

每一個Presenter還要暴露一些其他的方法, 對應View中使用者的行為.

MVP模式的缺點:
MVP模式很好地分離了概念, 當然這是好的. 但是當開發很小的app或者只是做一個原型時, 確實感覺過度設計了. 為了減少所用的介面, 有一些開發者省去了Contract介面類, 也刪掉了Presenter的介面.

當把UI的邏輯移到Presenter中時, 它就變成了一個全能的類, 程式碼很長. 為了解決這個問題, 可以進一步拆分程式碼, 並且記得建立單一職能, 並且可以被單元測試的類.

結論:
Model-View-Controller MVC模式 有兩個主要的缺點: 首先, View持有Controller和Model的引用; 第二, 它沒有把對UI邏輯的操作限制在單一的類裡, 這個職能被Controller和View或者Model共享.

MVP模式解決了這兩個問題: 砍斷了View和Model之間的聯絡, 用Presenter來管理所有和View顯示相關的邏輯(handles everything related to the presentation of the View), 並且這個類是很容易被單元測試的.

作者有三個buildTypes: debug, beta, release.

其中beta用了initWith(buildTypes.debug).
他想給不同的type加上不同的proguard files. 讓debug不混淆(-dontobfuscate), beta和release混淆.
結果卻發現beta沒有混淆.

檢視程式碼發現proguardFiles其實是將proguard files疊加.
作者找到的解決方式是用setProguardFiles():

buildTypes {
  debug {
    // ...
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'proguard-debug.pro'
  }

  beta {
    initWith(buildTypes.debug)
    // ...
    // New!
    setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'])
  }

  release {
    // ...
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  }

}

評論區有人指出還可以這樣:
defaultConfig中:

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

然後在debug中: 加proguardFile 'proguard-debug.pro, 這樣更簡潔一些.

作者使用例子介紹瞭如何將RxJava和Android的Data Binding結合起來使用.

因為Kotlin預設類和方法都是final的, 如果你想要繼承, 必須顯式宣告open.

當你想要在測試中Mock一些行為時, Mockito可能會報錯, 因為它無法mock一個final的class/method.

於是你可能要修改原始碼, 加open或者是介面, 僅僅是為了測試.

你只需要在resources/mockito-extensions目錄下建立一個檔案: org.mockito.plugins.MockMaker.
裡面只包含一行內容:
mock-maker-inline.

這兩篇是關於Droidcon NYC 2016的感想.

Gradle中的configuration是:

dependencies {
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
    compile 'com.jakewharton:butterknife:8.4.0'
    compile project(':api')
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4'
    androidTestCompile 'com.android.support.test:runner:0.5'
    testCompile 'org.robolectric:robolectric:3.1.2'
    testAnnotationProcessor 'org.robolectric:robolectric-processor:3.1.2'
}

模式是configuationName dependencyNotation.

Configuration names由兩部分組成:

  • 可選的字首, 指定build variant, product flavor或者build type.
  • 必需的字尾, 指定scope.

比如在debugCompile中, debug就是一個build type.

compile沒有字首, 就表示它應用到所有的build型別裡.

每一個正常的configuration都有一個相應的unit test版, 比如testCompile, testDebugCompile.

對於功能測試來說是androidTest, 只有這一種.

Scope

Scope是和configuration應用的階段有關:

  • annotationProcessor/kapt: 註解處理;
  • provided/compileOnly: 編譯期;
  • compile: 編譯 + 執行;
  • apk: 執行期.

繼承
Configuration可以繼承, 意味著子類包含父類所有包含的專案.
比如testCompile就繼承了compile.
但是注意繼承必須顯式宣告, 並不是由名字看出來的, 比如testAnnotationProcessor沒有繼承annotationProcessor.

利用繼承可以定義單元測試和公共測試的基類, 這樣它們的共享依賴就可以只宣告一次.

configurations {
 [androidTestCompile, testCompile].each { it.extendsFrom commonTestCompile }
}

LIBRARIES & CODE

例子程式碼, 展示如何結合RxJava和Android data binding.

一個Quick Settings tile, 用於控制動畫的duration scale.

一個關於日期和時間的自動提示輸入框.

一個Android所有許可權的列表.

NEWS

Mockito 2釋出了, 有什麼新東西呢?

Kotlin 1.0.5 EAP (Early Access Program).

android-apt將不會再開發了, 因為它的功能已經被包含進了Android Gradle plugin.