Android Weekly Issue #225
October 2nd, 2016
Android Weekly Issue #225
本期內(nèi)容包括: Android 7.0的Quick Settings; Firebase; 兼容舊版本的shared element transition; Wear; ORM: 用ActiveAndroid做數(shù)據(jù)庫存儲; 崩潰報告工具對比; Google Cast API介紹; Google的播放器庫ExoPlayer 2.x發(fā)布; 項目的包結(jié)構(gòu)整理; Task API的使用等等.
ARTICLES & TUTORIALS
Android 7.0的快速設置 Quick Settings Tiles
從Android 7.0 (API 24)開始, 任何app都可以創(chuàng)建一個quick settings tile, 快速訪問關鍵功能.
它除了是一個展示最新信息的UI, 點擊一個片還可以trigger后臺任務, 打開dialog或activity.
一個好的quick settings tile:
決定是否要建立這樣一個tile時, 主要考慮緊急性和頻繁性兩個方面.
每一個tile和一個TileService關聯(lián). 和其他service一樣, 它需要在manifest中注冊, 它的label和icon就是顯示在quick settings上的文字和圖片.
TileService的生命周期:
TileService是一個bound service, 它的生命周期主要由系統(tǒng)控制. 主要有三個階段: being added, listening, being removed.
-
onTileAdded(): 當用戶添加這個tile到quick settings. -
onStartListening(): tile變?yōu)榭梢? -
onStopListening(): tile變?yōu)椴豢梢? -
onTileRemoved(): 用戶移除這個tile.
以上這是默認模式, 如果你準確地知道何時更新, 你可以使用active mode.
此時更新的回調(diào)onStartListening()是通過靜態(tài)方法主動觸發(fā)的.
更新UI:
UI是Tile, 主要包含icon, label, description和state. 最后必須調(diào)用updateTile()方法.
處理點擊:
在onClick()回調(diào)觸發(fā)的時候, 我們可以啟動一些后臺工作, 或者showDialog(), 或者startActivityAndCollapse().
對于鎖屏的機器有一些限制, 不能打開dialog, 并且activity需要有一個特定的flag, 有一個unlockAndRun()方法可以讓用戶先解鎖后做一些工作.
長按tile默認會打開app的app info屏, 當然這個行為也可以override. 只要給你想打開的activity加上ACTION_QS_TILE_PREFERENCES.
Android開發(fā)最佳實踐 Android Development Best Practices
關于性能:
Best Practices for Performance;
Performance and Optimization
關于架構(gòu):
android-architecture
寫單元測試和UI測試.
使用Proguard, Stetho.
復用布局, 使用<merge>標簽.
reusing-layouts.
把launcher icons放在mipmap文件夾下.
多用shape和selector而不是圖片.
避免深層次的布局.
向Intent或Bundler傳數(shù)據(jù)時, 使用Parcelable而不是Serializable. 因為后者使用反射而比較慢.
不要在UI線程進行文件操作.
明白Bitmaps. 因為它們占用很多memory. Displaying Bitmaps
使用style來避免重復的屬性設置.
需要時使用Fragment.
明白Activity的生命周期.
使用得到公認的libraries而不是自己的實現(xiàn).
在各種機器上測試.
Recap Of Google Launchpad Build Lagos : All About Firebase
作者參加了一個叫Google Launchpad Build的會議, 這篇文章是總結(jié), 全部是關于Firebase的.
Android Shared-Element Transitions for all
在Lollipop+的設備上, shared element的transition動畫很好實現(xiàn), 但是在舊的版本上該怎么辦呢? 作者展示了他的方法:
- Activity A捕捉origin view的初始值, 通過Intent把它們傳給Activity B;
- Activity B完全透明地啟動;
- Activity B讀取bundle中的值, 準備場景;
- Acitivty B運行shared element動畫.
幾個實現(xiàn)細節(jié):
需要知道View在B中的位置, 時機是layout之后, 但是draw之前, 即onPreDraw().
返回時只需要把這個動畫反向播放即可.
Writing Better Adapters
(這個上一期剛講過, 不知道為什么重復了. )
就是關于RecyclerView的Adapter, 作者認為多種View類型時, Adapter中太多的instance of和強制類型轉(zhuǎn)換不是一種好做法, 于是提出了他的做法.
Android Wear: Accessing the Data Layer API
Data Layer API是Google Play services的一部分, 用于不同設備(手機和手表)間的數(shù)據(jù)交換.
作者先提供了代碼, 發(fā)送和存儲數(shù)據(jù), 監(jiān)聽數(shù)據(jù)變化.
問題是, 如果Wear第二次向mobile請求數(shù)據(jù), mobile發(fā)送了和上一次一樣的數(shù)據(jù), Wear并不會進入onDataChanged(), 因為數(shù)據(jù)并沒有變化.
所以作者想知道如何從Data Layer API來獲取數(shù)據(jù), 并展示了他的方法在不同情形下的應用.
Espresso Tests For TextSwitcher
作者想給TextSwitcher寫Espresso測試.
從Android Studio 2.2開始, 你可以錄制你的操作, IDE將會自動為你生成Espresso測試代碼. 但是作者錄了一個有關TextSwitcher的測試之后, 跑失敗了.
這是因為TextSwitcher繼承了ViewSwitcher, 其實現(xiàn)其實是把兩個TextView加到了布局里.
所以Espresso拋出了AmbiguousViewMatcherException.
所以作者根據(jù)可見性區(qū)分了它倆, 修復了測試.
還可以根據(jù)child view的index來區(qū)分.
Animating Android Activities and Views with Slide Animations
作者展示了如何給Activity和View加上左右滑動的動畫.
Guide to ORM using ActiveAndroid: Part 1
這是一個系列教程, 相關的代碼在: ActiveAndroid-Tutorial
什么是ORM(Object-Relational Mapping)呢?
a technique to convert between incompatible type-systems in an object-oriented programming language.
在面向?qū)ο蟮恼Z言中, 轉(zhuǎn)換不兼容的類型的技術.
ActiveAndroid是一個ORM(object relational mapper), 讓你不用寫SQL語句, 就可以讀寫數(shù)據(jù)庫.
A Comparison of Android Crash Reporting Tools
作者對比了幾種崩潰報告工具, 并介紹了如何使用.
包括: Firebase, Crashlytics, Apteligent, Bugsnag.
Google Play Services: Google Cast v3 and Media
Google Cast是一個讓用戶把網(wǎng)上的內(nèi)容發(fā)送到設備上的技術. 通常用來和TV交換內(nèi)容.
作者詳細地介紹了如何使用Google Cast SDK來創(chuàng)建應用.
注: 要建造客戶端程序, 首先需要注冊: https://cast.google.com/publish/.
這是收費的.
ExoPlayer 2.x - It’s here (plus FAQs)!
Google的庫google/ExoPlayer升級到v2.x了.
(它是一個Media Player, YouTube用的就是它.)
這次是個重大更新, 添加了很多新功能, 推薦大家以后用新版.
How We Rethought our Complete Package Structure for Buffer on Android
作者他們重新整理了項目的包結(jié)構(gòu), 總結(jié)了整個過程還有從中學到的東東.
作者他們之前的包結(jié)構(gòu)是按類型的, 有activities, fragments, adapters等包. 因為類名以類型終結(jié), 所以索性就按整個分組.
當app變得越來越大, 這種組織方式發(fā)現(xiàn)就不太好, 感覺很難找東西, 并且感覺沒什么結(jié)構(gòu).
經(jīng)過改變之后, 作者他們采用了一種更加整潔并且易于導航的結(jié)構(gòu).
新結(jié)構(gòu)中, 當添加一個新的feature, 就保持在同一個目錄中, 這樣就不用來回切換目錄.
作者他們的新結(jié)構(gòu)有四個總目錄:
- data
- ui
- injection
- util
data中包含網(wǎng)絡請求及相關的models, preferences, database, data models, 還有其他和數(shù)據(jù)直接關聯(lián)的東西.
其中和不同API關聯(lián)的models又分別組織在子目錄下.
ui目錄中包含所有和UI相關的組件, 在這個包中按照功能又拆分了子目錄. 其中有base包, 用來盛放Fragment, Activity和MVP的基類, 接口等; 還有common包, 用來盛放公共控件.
injection中包含所有依賴注入的類, 分component, module和scope的子目錄.
util中含有Helper和Utility類.
Become a Firebase Taskmaster! (Part 3)
這是系列文章的第三篇, 這個系列是關于Play services的Task API.
如果項目里已經(jīng)依賴了Firebase, 變自動包含了Task API, 如果不想用Firebase, 可以單獨添加依賴:
compile 'com.google.android.gms:play-services-tasks:9.6.1'
創(chuàng)建新的Task可以用下面這兩個方法:
Task<TResult> call(Callable<TResult> callable)
Task<TResult> call(Executor executor, Callable<TResult> callable)
第一個call()方法在主線程執(zhí)行任務, 第二個call()方法可以把工作提交給一個Executor.
Callable有點類似于Runnable:
public class CarlyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Call me maybe";
}
}
參數(shù)制定了方法的返回值的類型, 進而也是創(chuàng)建出Task的類型.
Task<String> task = Tasks.call(new CarlyCallable());
想要鏈式執(zhí)行, 進行后續(xù)操作, 可以用Continuation.
public class SeparateWays implements Continuation<String, List<String>> {
@Override
public List<String> then(Task<String> task) throws Exception {
return Arrays.asList(task.getResult().split(" +"));
}
}
它繼承接口時指定了輸入和輸出的類型, 它的輸入來自于Task的輸出.
可以多寫幾個Continuation類然后連起來:
Task<String> playlist = Tasks.call(new CarlyCallable())
.continueWith(new SeparateWays())
.continueWith(new AllShookUp())
.continueWith(new ComeTogether());
playlist.addOnSuccessListener(new OnSuccessListener<String>() {
@Override
public void onSuccess(String message) {
// The final String with all the words randomized is here
}
});
LIBRIARIES & CODE
groupie
顯示和管理復雜的RecyclerView布局, 把你的items按照邏輯分組管理.
android-junit5
Gradle插件, 用JUnit5做Android的單元測試.
epoxy
用來構(gòu)建復雜的RecyclerView屏.