前言
工欲善其事必先利其器!在現代IT中,每個Android程式員都需要最好的工具來提高他們的技能和效率,在Android應用程式開發這個殘酷的競爭行業中,只有優秀的程式員才能生存下去,你需要向客戶展示你擁有的最佳技術和能力,
不僅僅是展示你的設備以吸引客戶,還要確保你的Android應用程式在高效的時間內以最高質量構建,那么哪些是最好的Android開發者工具?有很多選擇,但并非所有工具都足夠好,在不浪費任何時間的情況下,讓我們來看看以下的Android應用開發工具,
1、MVVM架構模式概覽
這是使用MVVM架構模式+Kotlin協程+JetPack(ViewModel+LiveData)+Retrofit的架構,實作WanAndroid登錄介面的小DEMO,后續會慢慢完善WanAndroid客戶端
1、ViewModel
為了從界面控制器Activity/Fragment邏輯中分離出視圖View資料所有權,架構組件為界面控制器提供了 ViewModel 輔助程式類,該類負責為界面準備資料,在配置更改期間會自動保留 ViewModel 物件,以便它們存盤的資料立即可供下一個 Activity 或 Fragment 實體使用,
2、LiveData
LiveData 是一種可觀察的資料存盤器類,具有生命周期感知能力,意指它遵循其他應用組件如 Activity、Fragment 或 Service 生命周期,可確保 LiveData 僅更新處于活躍生命周期狀態的應用組件觀察者,LiveData 物件通常存盤在 ViewModel 物件中,并可通過 getter 方法進行訪問,
3、Kotlin協程
協程依附在執行緒上,可以實作順序撰寫異步代碼,自動進行執行緒切換,并且ViewModelScope為應用中的每個 ViewModel 定義了 ViewModelScope,如果 ViewModel 已清除,則在此范圍內啟動的協程都會自動取消,
4、Retrofit
將服務介面中的網路請求函式宣告為suspend掛起介面函式,以支持Kotlin執行緒,并將suspend函式結果作為 LiveData 物件傳送,

2、ViewModel
//獲取ViewModel
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)`
ViewModel 物件存在的時間范圍是獲取 ViewModel 時傳遞給 ViewModelProvider 的 Lifecycle,ViewModel 將一直留在記憶體中,直到限定其存在時間范圍的 Lifecycle 永久消失:對于 Activity,是在 Activity 完成時;而對于 Fragment,是在 Fragment 分離時,

3、LiveData
//對User資料進行觀察
viewModel.user.observe(this, Observer {
//展示登錄結果
if (it.errorCode == 0) {
Toast.makeText(this, it.data?.nickname, Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, it.errorMsg, Toast.LENGTH_SHORT).show()
}
})
使用 LiveData 具有以下優勢:確保界面符合資料狀態
LiveData 遵循觀察者模式,當生命周期狀態發生變化時,LiveData 會通知 Observer 物件,您可以整合代碼以在這些 Observer 物件中更新界面,觀察者可以在每次發生更改時更新界面,而不是在每次應用資料發生更改時更新界面,
不會發生記憶體泄漏
觀察者會系結到 Lifecycle 物件,并在其關聯的生命周期遭到銷毀后進行自我清理,
不會因 Activity 停止而導致崩潰
如果觀察者的生命周期處于非活躍狀態(如回傳堆疊中的 Activity),則它不會接收任何 LiveData 事件,
不再需要手動處理生命周期
界面組件只是觀察相關資料,不會停止或恢復觀察,LiveData 將自動管理所有這些操作,因為它在觀察時可以感知相關的生命周期狀態變化,
資料始終保持最新狀態
如果生命周期變為非活躍狀態,它會在再次變為活躍狀態時接收最新的資料,例如,曾經在后臺的 Activity 會在回傳前臺后立即接收最新的資料,
適當的配置更改
如果由于配置更改(如設備旋轉)而重新創建了 Activity 或 Fragment,它會立即接收最新的可用資料,
共享資源
可以使用單一實體模式擴展 LiveData 物件以封裝系統服務,以便在應用中共享它們,

4、Kotlin協程
4.1、異步的本質
什么是異步?
異步就是同時進行一個以上彼此目的不同的任務,
但是對于有前后依賴關系的任務,異步該如何處理呢?
利用異步中的回呼機制處理,
為什么需要異步回呼機制?
因為不同的任務之間存在前后的依賴關系,
異步回呼機制有什么缺點?
代碼結構過分耦合,遇到多重函式回呼的嵌套耦合,也就是回呼地獄,代碼會難以維護,
解決回呼地獄的方案有什么?
鏈式呼叫結構,
常見方式就是使用RxJava,它是反應函式式編程在Java中的實作,
但是RxJava中流的創建、轉化與消費都需要使用到各種類和豐富的運算子,加大了RxJava的學習成本,
減少在無封裝情況下使用RxJava,因為你無法保證團隊里面的每一個成員都能看懂它,并且在修改時都能做出正確選擇,
在串行的執行中,雖然代碼確實是順序執行的,但其實是在不同的執行緒上順序執行的,那為什么在串行的執行中代碼執行順序一致,卻還要使用回呼呢?
因為串行的執行中,執行是阻塞式的,主執行緒的阻塞會導致很嚴重的問題,所以所有的耗時操作不能在主執行緒中執行,所以就需要多執行緒并行來執行,
在并行的執行中,異步回呼其實就是代碼的多執行緒順序執行,那能不能既按照順序的方式撰寫代碼,又可以讓代碼在不同的執行緒順序執行,自動完成執行緒的切換作業呢?
那就是Kotlin協程,
Kotlin 的協程是一種無堆疊協程的實作,它的控制流轉依靠對協程體本身編譯生成的狀態機的狀態流轉來實作,變數保存也是通過閉包語法來實作的,
結論:
異步回呼就是代碼的多執行緒順序執行,而Kotlin協程可以實作順序撰寫異步代碼,自動進行執行緒切換,
那么協程自動進行執行緒切換的原理是什么?
Yield:讓出CPU,放棄調度控制權,回到上一次Resume的地方
Resume:獲取調度控制權,繼續執行程式,到上一次Yield的地方
例子:
1. GlobalScope.launch發起了一個協程,并在IO執行緒上執行,
2\. 在協程里,去呼叫介面獲取結果,
3. 拿到結果,使用withContext(Dispatchers.Main)切換到主執行緒并更新界面
4.2、協程的型別
是協程范圍,指的是協程內的代碼運行的時間周期范圍,如果超出了指定的協程范圍,協程會被取消執行,
GlobalScope
指的是與應用行程相同的協程范圍,也就是在行程沒有結束之前協程內的代碼都可以運行,
JetPack中提供的生命周期感知型協程范圍:
ViewModelScope,為應用中的每個 ViewModel 定義了 ViewModelScope,如果 ViewModel 已清除,則在此范圍內啟動的協程都會自動取消,
LifecycleScope,為每個 Lifecycle 物件定義了 LifecycleScope,在此范圍內啟動的協程會在 Lifecycle 被銷毀時取消,
使用 LiveData 時,可能需要異步計算值,可以使用 liveData 構建器函式呼叫 suspend 函式,并將結果作為 LiveData 物件傳送,
相關鏈接:https://developer.android.google.cn/topic/libraries/architecture/coroutines
4.3、協程的啟動
launch方法:
/**
* 重要知識:ViewModel+協程
*/
fun ViewModel.launch(
block: suspend CoroutineScope.() -> Unit,
one rror: (e: Throwable) -> Unit = {},
onComplete: () -> Unit = {}
) {
viewModelScope.launch(CoroutineExceptionHandler { _, e -> one rror(e) }) {
try {
block.invoke(this)
} finally {
onComplete()
}
}
}
原始碼:
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
4.3.1、launch方法解釋
context
協程背景關系,可以指定協程運行的執行緒,默認與指定的CoroutineScope中的coroutineContext保持一致,比如GlobalScope默認運行在一個后臺作業執行緒內,也可以通過顯示指定引數來更改協程運行的執行緒,Dispatchers提供了幾個值可以指定:Dispatchers.Default、Dispatchers.Main、Dispatchers.IO、Dispatchers.Unconfined,
start
協程的啟動模式,默認的CoroutineStart.DEFAULT是指協程立即執行,除此之外還有CoroutineStart.LAZY、CoroutineStart.ATOMIC、CoroutineStart.UNDISPATCHED,
block
協程主體,也就是要在協程內部運行的代碼,可以通過lamda運算式的方式方便的撰寫協程內運行的代碼,
CoroutineExceptionHandler
指定CoroutineExceptionHandler來處理協程內部的例外,
Job
回傳值,對當前創建的協程的參考,可以通過Job的start、cancel、join等方法來控制協程的啟動和取消,
4.4、suspend掛起函式
suspend關鍵字只起到了標志這個函式是一個耗時操作,必須放在協程中執行的作用,而withContext方法則進行了執行緒的切換作業,
協程中的代碼自動地切換到其他執行緒之后又自動地切換回了主執行緒!順序撰寫保證了邏輯上的直觀性,協程的自動執行緒切換又保證了代碼的非阻塞性,掛起函式必須在協程或者其他掛起函式中被呼叫,也就是掛起函式必須直接或者間接地在協程中執行,
那為什么協程中的代碼沒有在主執行緒中執行呢?而且執行完畢為什么還會自動地切回主執行緒呢?
協程的掛起可以理解為協程中的代碼離開協程所在執行緒的程序,協程的恢復可以理解為協程中的代碼重新進入協程所在執行緒的程序,協程就是通過的這個掛起恢復機制進行執行緒的切換,
4.5、async await方法
用async方法包裹了suspend方法來執行并發請求,并發結果都回傳之后,切換到主執行緒,接著再用await方法來獲取并發請求結果,
5、Retrofit
HTTP介面suspend掛起函式:
interface ApiService {
@FormUrlEncoded
@POST("user/login")
suspend fun loginForm(@Field("username") username: String,@Field("password") password: String): BaseResponse<User>
}
kotlin泛型:
data class BaseResponse<T>(
val errorCode: Int=0,
val errorMsg:String? = null,
var data: T? = null
)
這是使用MVVM架構模式+Kotlin協程+JetPack(ViewModel+LiveData)+Retrofit的架構,實作WanAndroid登錄介面的小DEMO,后續會慢慢完善WanAndroid客戶端
最后相關架構及資料領取方式:
點擊我的騰訊檔案免費領取獲取往期Android高級架構資料、原始碼、筆記、視頻,高級UI、性能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)微信小程式、Flutter全方面的Android進階實踐技術,群內還有技術大牛一起討論交流解決問題,
otlin協程+JetPack(ViewModel+LiveData)+Retrofit的架構,實作WanAndroid登錄介面的小DEMO,后續會慢慢完善WanAndroid客戶端
最后相關架構及資料領取方式:
點擊我的騰訊檔案免費領取獲取往期Android高級架構資料、原始碼、筆記、視頻,高級UI、性能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)微信小程式、Flutter全方面的Android進階實踐技術,群內還有技術大牛一起討論交流解決問題,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/279285.html
標籤:其他
