- Android Jetpack開發(fā):原理解析與應(yīng)用實戰(zhàn)
- 黃林晴
- 933字
- 2022-07-05 09:43:58
3.1 什么是ViewModel
按照官方描述,ViewModel類旨在以注重生命周期的方式存儲和管理界面相關(guān)的數(shù)據(jù)。ViewModel類可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后讓數(shù)據(jù)繼續(xù)留存。
上面的描述怎么理解呢?這里通過上一章遺留的問題來說明。在上一章中使用Lifecycle實現(xiàn)了廣告引導(dǎo)頁的需求,即用戶打開App進入引導(dǎo)頁面,倒計5秒后進入主頁面,正常操作下運行日志如圖3-1所示。

圖3-1 正常操作下的運行日志
如果在廣告剩余2秒的時候?qū)⑹謾C屏幕旋轉(zhuǎn),那么打印日志如圖3-2所示。

圖3-2 廣告剩余2秒旋轉(zhuǎn)屏幕日志
通過圖3-2可以發(fā)現(xiàn),屏幕旋轉(zhuǎn)后,原有計時停止后又重新開始了。出現(xiàn)這個問題的原因是當(dāng)屏幕旋轉(zhuǎn)時Activity被銷毀后又重新創(chuàng)建了。
注意
屏幕旋轉(zhuǎn)時,生命周期的變化取決于configChanges屬性,這里未配置config-Changes的屬性,所以屏幕由豎屏切換為橫屏?xí)r,會重新執(zhí)行每個生命周期方法。讀者可自行查閱configChanges的其他屬性值。
這種結(jié)果用戶肯定是不能接受的,因為旋轉(zhuǎn)屏幕操作導(dǎo)致用戶需要重復(fù)觀看廣告。這個問題一般如何處理呢?一種方式是通過修改configChanges屬性使得App在旋轉(zhuǎn)的時候不被銷毀,但因為有其他業(yè)務(wù)邏輯限制,所以這里不考慮。另一種常用的方式是通過重寫onSaveInstanceState方法在Activity被銷毀的時候?qū)?dāng)前計時的節(jié)點存儲起來,重新開始計時的時候從上次計時的節(jié)點開始計時。
在使用這種方式處理之前,首先需要修改上一章中AdvertisingManage的代碼計時器,將計時的起止時間修改為傳參的形式,示例代碼如下:
class AdvertisingManage(millisInFuture: Long = 5000) : LifecycleObserver { ... //定時器 private var countDownTimer: CountDownTimer? = object : CountDownTimer(millisInFuture, 1000) { ... }
這樣修改后,每次計時都會將當(dāng)前的計時記錄下來,便于下一次使用。示例代碼如下:
//計時的時長,默認(rèn)值5秒 var millisInFuture: Long = 5000 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... val advertisingManage = AdvertisingManage(millisInFuture) ... advertisingManage.advertisingManageListener = object : AdvertisingManage.AdvertisingManageListener { override fun timing(second: Int) { tvAdvertisingTime.text = "廣告剩余$second秒" millisInFuture = second.toLong() * 1000 } ..... }
接著在Activity中重寫onSaveInstanceState方法,記錄Activity銷毀時計時的節(jié)點。在第二次創(chuàng)建AdvertisingManage實例的時候?qū)⑦€需要計時的時間傳給Advertising-Manage類。示例代碼如下:
//計時的時長,默認(rèn)值5秒 var millisInFuture: Long = 5000 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... savedInstanceState?.let { millisInFuture = it.getLong(KEY_MILLISINFUTURE) } val advertisingManage = AdvertisingManage(millisInFuture) ... } ... override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putLong(KEY_MILLISINFUTURE, millisInFuture) } companion object { //key計時的開始時間 const val KEY_MILLISINFUTURE = "keyMillsimfuture" }
修改上述代碼之后,進行與前面相同的操作——廣告剩余2秒時將手機屏幕旋轉(zhuǎn)。打印日志如圖3-3所示。

圖3-3 廣告剩余2秒時旋轉(zhuǎn)屏幕的日志
通過打印的日志可以看到,在2秒時停止計時,屏幕旋轉(zhuǎn)后從1s開始計時,符合預(yù)期效果。上面是通過onSaveInstanceState方法來解決屏幕旋轉(zhuǎn)導(dǎo)致廣告重新計時這一問題的。那么是否有更優(yōu)雅的解決方案呢?
- Java EE框架整合開發(fā)入門到實戰(zhàn):Spring+Spring MVC+MyBatis(微課版)
- 深入淺出Prometheus:原理、應(yīng)用、源碼與拓展詳解
- MATLAB定量決策五大類問題
- Julia Cookbook
- Mastering Predictive Analytics with Python
- 大模型RAG實戰(zhàn):RAG原理、應(yīng)用與系統(tǒng)構(gòu)建
- 微信小程序項目開發(fā)實戰(zhàn)
- SQL Server與JSP動態(tài)網(wǎng)站開發(fā)
- Visual C#.NET Web應(yīng)用程序設(shè)計
- Swift語言實戰(zhàn)晉級
- Web程序設(shè)計:ASP.NET(第2版)
- Python Programming for Arduino
- Android編程權(quán)威指南(第4版)
- 虛擬現(xiàn)實:引領(lǐng)未來的人機交互革命
- Java項目驅(qū)動開發(fā)教程