Android Weekly Notes Issue #255
Android Weekly Issue #255
April 30th, 2017
Android Weekly Issue #255
本期內容包括: 一種在RxJava中顯示loading/content/error的好的處理方法; Android O中的一些隱藏寶藏; Uber app的immutable的資料升級; MVP模式下, 不要再做view != null
的判斷了; 用Dagger2實現的依賴注入; 遷移應用到Kotlin; 如何把Gradle外掛從Groovy遷移到Kotlin; Activity中的靜態start方法使用; Firebase的實時資料庫使用.
ARTICLES & TUTORIALS
LCE: Modeling Data Loading in RxJava
作者介紹了一種方法, 用RxJava來處理顯示loading/內容/錯誤的邏輯.
核心思想是中這個結構把資料包一層:
// Lce -> Loading / Content / Error
class Lce<T> {
public static <T> Lce<T> data(T data) {
// implementation
}
public static <T> Lce<T> error(Throwable error) {
// implementation
}
public static <T> Lce<T> loading() {
// implementation
}
boolean isLoading();
boolean hasError();
Throwable getError();
T getData();
}
然後實際處理的程式碼就變成了這樣:
repository.getDataEventStream().subscribe({ event ->
if (event.isLoading) {
view.showLoading(true)
} else if (event.hasError()) {
view.showError(event.getError())
} else {
view.showData(event.getData())
}
})
怎麼構建這個Observable呢:
Observable<Lce<Data>> getDataEventStream() {
return api.getData()
.map(data -> Lce.data(data))
.startWith(Lce.loading())
.onErrorReturn(e -> Lce.error(e))
}
更多構建方法見原文.
Hidden Gems of Android O
作者仔細看了Android O的API Diff, 然後發現了一些隱藏的寶藏拿出來分享.
- Storage Access Framework的改進.
- RecoverableSecurityException.
- SharedPreferences支援更換底層實現.
-
SmsManager.createAppSpecificSmsToken()
提供的更好的簡訊驗證流. - 鎖屏情況下的顯示處理:
Keyguard.dismissKeyguard()
. - 全屏Activity的旋轉處理.
Engineering Stability in Migrations
Uber的資料類生成及遷移到Immutable Collections的過程.
Don’t put view != null checks in your Presenters
如果你使用了MVP模式, 並且你的presenter在configuration變化時是一直存在的, 那麼你的presenter至少會有下面兩個方法:
void attachView(View)
void detachView()
這樣的話你的getView()
方法應該被標記為@Nullable
, 然後你就需要在很多地方做null判斷, 即便有些地方你100%地肯定View肯定不為null.
Presenter的方法直接從View中被呼叫
比如那些View中UI控制元件點選導致的呼叫.
加個view != null
的判斷有一個缺點就是如果attach時出現了問題, 這時使用者點選了按鈕卻沒有反應, 這個錯誤會被忽略和隱藏起來. 在這種View應該存在的情形下, 如果得到了null, 應該及時丟擲異常發現錯誤.
It’s always a bad sign when the else branch is missing.
解決方案: 加個@NonNull View getViewOrThrow()
方法:
@Nullable
public MyView getView() {...}
@NonNull
public MyView getViewOrThrow() {
final MyView view = getView();
if (view == null) {
throw new IllegalStateException("view not attached");
}
return view;
}
在Presenter中非同步呼叫View
很多時候我們需要非同步呼叫View的方法, 這時候我們就不能用getViewOrThrow()
了, 因為View被detach是一種合理的情況.
這時候我們如果加個if (view != null)
是可以解決這個問題的, 但是卻是一個錯誤的選擇. 因為else分支的缺失, 使用者可能錯過了server返回的結果, 然後永遠地等下去.
一個比較好的解決方案就是ThirtyInch, 它有一個方法叫sendToView(ViewAction), 它會推遲ViewAction
的執行, 到View再次被attach的時候執行. 如果View已經處於attached的狀態, 那麼就立即執行.
一個例子:
public class MyPresenter extends TiPresenter<MyView> {
public void onSubmitLogin(final Credentials credentials) {
mLoginService.login(credentials).subscribe(
success -> {
sendToView(view -> view.close());
},
error -> {
sendToView(view -> view.showError(error));
});
}
}
注意請不要過度使用sendToView()
.
如果你用MVI模式, 維護一個ViewModel, 在變化的時候渲染到View, 同樣也可以刪掉view != null
的判斷. 見My take on Model View Intent (MVI) — Part 1: State Renderer.
Optional和WeakReference
這篇文章中用了view == null
作為View被detached了的依據. 如果你使用了其他的包裝, 比如WeakReference
或者Optional
, 你雖然不用null判斷了但是並不代表你解決了問題, 你需要做其他的判斷並且lint不能幫你做提示了.
結論
你並不需要if (view != null)
檢查:
- 當你確定View是attached時, 使用
getViewOrThrow()
. - 當View可能會是detached時, 使用
sendToView(ViewAction)
, 來支援else的處理.
Dependency Injection in Android with Dagger 2
一個用了Retrofit和MVP模式的應用, 用Dagger2做依賴注入的例子.
How we made Basecamp 3’s Android app 100% Kotlin
作者他們如何把應用改為用Kotlin.
Migrate a Gradle Plugin from Groovy to Kotlin
如何把一個用Groovy寫的Gradle外掛轉化成Kotlin寫的.
Object Oriented Tricks: #4 Starter Pattern
在Activity中定義一個靜態的start()
方法, 把需要放在intent中的引數都當做方法引數傳進來.
Android Studio對此有一個內建的模板, 你只要輸入starter
, 按回車就可以生成這個方法.
Using Firebase as a Real Time System
Firebase的Real Time Database.
資料庫儲存的資訊以NoSQL的形式放在Google Cloud上.
三個主要的優點: 實時,離線處理, 自動同步.
文中展示了基本的用法.
之後提供了實時資料庫的幾種使用思路:
- 實時通訊: (Firechat);
- 顯示實時位置的地圖(Realtime geolocation tracking with Firebase, geofire);
- 排名.
LIBRARIES & CODE
Bubble-Picker
氣泡選擇器.
UltimateAndroidReference
Android資源收集, 包括庫, 開源專案, 書籍部落格等等.
litho-picasso
為Litho寫的picasso庫.
相關文章
- Flutter Weekly Issue 44Flutter
- Xamarin.Android提示aapt退出,程式碼為255AndroidAPT
- issue
- Flutter Notes | Android 借殼分享微信FlutterAndroid
- Android 開發技術週報 Issue#288Android
- Android 開發技術週報 Issue#279Android
- pymysql KeyError:255MySqlError
- Android 開發技術週報 Issue#269Android
- Oracle LOB issueOracle
- fir.im Weekly - 如何進行 Android App 效能優化AndroidAPP優化
- rac vip failback issueAI
- Linux locale issueLinux
- FreeMarker boolean IssueBoolean
- Android Notes|細數「十大布局」那些事兒Android
- Dependencies Among Other Remote Schema Objects (255)REMObject
- 前端如何設定背景顏色的透明度 css中的 rgba() 函式詳解 :background-color: rgba(255,255,255,0)前端CSS函式
- Mongodb NotesMongoDB
- Typora Notes
- ACM notesACM
- Weekly Contest 387
- Oracle Performance Top Issue listOracleORM
- fir.im Weekly - 2016 年 Android 最佳實踐列表Android
- Codeforces Round #FF(255) DIV2
- js 判斷 字元的長度255JS字元
- WireGuard Use Notes
- fir.im Weekly - iOS / Android 動態化更新方案盤點iOSAndroid
- fir.im Weekly - 8 個不能錯過的 iOS / Android 技術分享iOSAndroid
- Check connection related issue of mysqlMySql
- EOSIO MySQL 外掛 issue 2MySql
- EOSIO MySQL 外掛 issue 1MySql
- codeforces255C.Almost Arithmetical Progression
- c++stl notesC++
- Linux配置notesLinux
- BlockRecover Restrictions and Usage NotesBloCREST
- Make notes for disaster recoveryAST
- Thinking in java notesThinkingJava
- Oracle BI Answers Direct Database Request issueOracleDatabase
- Step 7: Issue the CREATE DATABASE Statement (65)Database