根據咱們曾經作的調查,開發者們但願 Android 官方能夠維護一些實用的組件庫和架構實踐,以下降中大型應用的開發門檻,這樣開發團隊就能夠集中更多精力在實際業務的優化和改進上。html
Jetpack 項目正是爲了解決這些問題而誕生的,Jetpack 是一系列助力您更容易打造優秀 Android 應用的工具和組件,這些組件能幫助您遵循最佳實踐、免除編寫繁複的樣板代碼並簡化複雜任務,從而使您能夠專一於最核心的代碼邏輯。其中 androidx.* 庫與 Framework API 解耦,這可以提供向後兼容的同時,也能更頻繁地更新。android
Android Jetpack 中的架構組件可幫助您設計穩健、可測試且易維護的應用。從最初發布的管理 Activity 和 Fragment 生命週期的Lifecycle 庫和訪問 SQLite 數據庫的 Room 庫,後來推出了分頁 (Paging)、導航 (Navigation) 和管理後臺任務的WorkManager 庫。根據 2019 年最新的開發者調查中,70% 以上的專業開發者用過這五個庫當中的至少一個庫進行應用開發。數據庫
這裏咱們分上下兩篇介紹架構組件的最新更新,若是您尚未閱讀本文的上篇,請點擊這裏查看《Android 架構組件的最新進展 (上篇) 》。本篇將會繼續爲你們介紹分頁庫、Room 持久性庫和 WorkManager。但願你們能在其中發現對本身的應用有幫助的全新功能以及改進:bash
Paging (分頁) 使得開發者能夠逐步、高效地加載大量數據,從而節省用戶的電池和流量。並且它和架構組件中的其餘部分或者其餘技術都能配合使用,好比 Room, Realm, Retrofit 等等。網絡
爲了讓分頁的使用更加便捷,在不久將來的版本里咱們將提供:架構
Room 是一個在 SQLite 上提供抽象層的持久存儲庫,您能夠回顧咱們以前的介紹文章瞭解更多 Room 的詳細信息。app
協程處理框架
在 Room 2.1 中,開發者能夠經過 Kotlin 語言的 suspend 關鍵字讓 Room 生成正確的協程代碼,包括使用後臺 dispatcher,這大大下降了開發者處理協程的工做量:ide
// Room 2.1
@Query("SELECT * FROM song WHERE songId = :songId")
suspend fun getSong(songId: String): Song
@Insert
suspend fun insertSong(song: Song)
@Transaction
suspend fun deleteShortSongs(): List<Song> {
val songs = getSongsWithElapsedTimeLessThan(1000)
deleteSongsWithIds(songs.map { it.songId })
return songs
}
複製代碼
另外,在 Room 2.1 中也提供了擴展函數讓開發者方便地啓動事務。它還會提供一個協程上下文 (CoroutineContext),這樣開發者能夠更方便地執行多個數據庫操做:函數
database.withTransaction {
val songs = getSongsWithElapsedTimeLessThan(1000)
deleteSongsWithIds(songs.map { it.songId })
return songs
}
複製代碼
全文搜索
全文搜索功能是對 SQLite 的一個擴展,讓其建立一個數據表從而更高效地檢索數據。
在 Room 2.0 中,一個 Dao 的檢索方法看起來多是這樣:
// Room 2.0
@Dao
interface SongDao {
@Query(""" SELECT * FROM Song WHERE songName LIKE ‘%’ || :query || ‘%’ OR albumName LIKE ‘%’ || :query || ‘%’ OR artistName LIKE ‘%’ || :query || ‘% """)
fun searchSongs(query: String): List<Song>
}
複製代碼
△ 注意 WHERE 和 OR 語句的長度
而在 2.1 中,只須要加入一個 @Fts4 註解,就能夠經過 MATCH 語句讓一切都輕鬆不少:
// Room 2.1
@Entity
@Fts4
data class Song(
@PrimaryKey
@ColumnInfo(name = "rowid")
val id: Long,
val url: String,
val songName: String,
val albumName: String,
val artistName: String
)
@Dao
interface SongDao {
@Query(""" SELECT * FROM Song WHERE Song MATCH :query """)
fun searchSongs(query: String): List<Song>
}
複製代碼
數據庫視圖
很像數據表,但又不徹底同樣。基本上,您能夠像檢索數據表同樣檢索數據庫視圖,但不能在其中插入數據。
在 2.1 中,您能夠用 @DatabaseView 註解您的數據類,但這時您不須要建立一個數據表,而是直接將 BigQuery 放在註解部分,讓其成爲一個能快速檢索的視圖:
@DatabaseView(""" SELECT Album.*, count(song_id) AS num_of_songs, sum(song_elapsed_time) AS total_time FROM Album JOIN AlbumSongRef ON (album_id = ref_album_id) JOIN Song ON (ref_song_id = song_id) GROUP BY album_id """)
data class AlbumItem(
@Embedded
val album: Album,
@ColumnName("num_of_songs")
val numOfSongs: Int,
@ColumnName("total_time")
val totalTime: Long
)
複製代碼
而這個視圖 (如上面的 AlbumItem) 能夠像其餘數據表同樣使用:
@Query(""" SELECT * FROM AlbumItem ORDER BY num_of_songs DESC """)
fun getAlbumItemsByNumOfSongs(): List<AlbumItem>
複製代碼
擴展的 Rx 支持
在 Room 2.1 中,您使用的 insert, update, delete 方法能返回 Completable, Maybe 和 Single。並且在 Query 註解的方法裏可使用 Rx 做爲返回類型,並處理 update, insert 或者 delete 這樣的寫入操做:
@Insert
fun addSong(song: Song): Completable
@Update
fun updateSong(song: Song): Single<Int>
@Query(""" UPDATE Song SET lastPlayedTime = :time WHERE id = :id """)
fun updateSongPlayTime(Long: time, String: id): Completable
複製代碼
Room 接下來會實現增量註解處理,提升構建速度,另外也會進一步提高關係數據的處理效率,並提高數據遷移的便利性。在協程方面,則會加入 Channel 和 Flow 的支持。
WorkManager 是一個後臺進程庫,用於處理那些不須要即時處理的任務,並且能夠在應用甚至設備重啓後依然確保任務正確觸發。另外,WorkManager 也支持按條件啓動,好比根據網絡鏈接情況的變化啓動特定的任務。
性能和兼容性
按需配置
以往 WorkManager 須要在應用啓動時就初始化,而按需配置 (On-demand Configuration) 可讓開發者僅在須要時才啓動 WorkManager。在 WorkManager 2.1 中,您能夠經過重載 Configuration.Provider 中的方法來得到一個 WorkManager 的配置對象。
// WorkManager 2.1.0
class MyApp : Application(), Configuration.Provider {
override fun getWorkManagerConfiguration() : Configuration {
return Configuration.Builder()
// set your options here
.build()
}
}
複製代碼
在目前 WorkManager 2.0 中 WorkManager.getInstance() 方法並不須要開發者提供參數,而在 2.1 中開發者傳入 context 參數後,WorkManager 若是沒有初始化,它會基於參數訪問 application 對象並獲取到配置:
WorkManager.getInstance().enqueue(...)
複製代碼
Google Play services 集成
此功能即將到來,並且提高了在 Marshmallow 以前版本的設備上的運行性能。並且這個集成是可選的,開發者能夠根據須要自行選擇是否集成。
兼容性改進
兼容性方面,咱們主要是在作 "幕後工做"。好比和 OEM 溝通,確保不一樣的設備能擁有一致的應用退出操做。
測試
第一點,也是開發者們一直有提到的: Robolectric 支持。Robolectric 是一個高效可靠的 Android 單元測試框架,如今已被全面支持。
第二點,Worker 已提供單元測試的支持。
您可使用 TestWorkerBuilder:
// WorkManager 2.1.0
// Create a test worker
val request = OneTimeWorkRequestBuilder<MyWorker>.build()
val worker = TestWorkerBuilder
.from(context, request, executor)
.build()
// Test its behavior
val result = worker.doWork()
assertThat(result, `is`(Result.success()))
assertThat(...)
複製代碼
也可使用 TestListenableWorkerBuilder:
// WorkManager 2.1.0
// Or create a listenable worker
val request = OneTimeWorkRequestBuilder<MyWorker>.build()
val listenableWorker = TestListenableWorkerBuilder
.from(context, request)
.build()
// Test its behavior
val result = listenableWorker.startWork().get()
assertThat(result, `is`(Result.success()))
assertThat(...)
複製代碼
WorkManager 的下一步
咱們正在努力實現前臺服務的支持,讓您能夠在前臺也能使用 WorkManager API。
感謝你們對本次連載的關注,但願在瞭解完架構組件的最新進展後,你們能在其中找到適合本身應用的功能。您也能夠觀看 ☟下面的視頻☟ 重溫咱們對架構組件進展的介紹。
若是對架構組件有疑問或者建議,歡迎在評論區和咱們分享。
點擊這裏進一步瞭解 Android Jetpack