- Android Jetpack开发:原理解析与应用实战
- 黄林晴
- 594字
- 2022-07-05 09:43:59
3.2 使用ViewModel解决广告引导页屏幕旋转问题
在上一节中提到了ViewModel类可在发生屏幕旋转等配置更改后让数据继续留存,这时,细心的读者就会思考了,该如何使用ViewModel来解决广告引导页屏幕旋转问题呢?
在使用ViewModel之前,先引入ViewModel的依赖项,代码如下:
def lifecycle_version = "2.3.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
然后新建一个继承自ViewModel的AdvertisingViewModel类,在该类中声明计时起始变量millisInFuture,代码如下:
class AdvertisingViewModel : ViewModel() { /** * 计时开始时间,默认5秒 */ var millisInFuture: Long = 5000 }
若开发者想在ViewModel类中使用资源文件,则要使用到Context上下文了。这里要注意的是,一定不能将Activity的上下文传给ViewModel,否则会存在内存泄漏的风险。这一点本书后面会有详细的讲解。那这里该如何处理呢?只需要将父类ViewModel修改为AndroidViewModel即可。示例如下:
class AdvertisingViewModel(application: Application) : AndroidViewModel(application) { /** * 计时开始时间,默认5秒 */ var millisInFuture: Long = 5000 }
拥有Application的实例之后就可以访问资源文件了。在Activity中初始化ViewModel,示例如下:
private lateinit var advertisingViewModel: AdvertisingViewModel override fun onCreate(savedInstanceState: Bundle?) { ... advertisingViewModel = ViewModelProvider(this).get(AdvertisingViewModel::class.java) ... }
接下来只需要将原Activity中的millisInFuture变量统一替换为AdvertisingView-Model中的millisInFuture即可。示例代码如下:
class AdvertisingActivity : AppCompatActivity() { ... private lateinit var advertisingViewModel: AdvertisingViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_advertising) advertisingViewModel = ViewModelProvider(this).get(AdvertisingViewModel::class.java) val advertisingManage = AdvertisingManage(advertisingViewModel.millisInFuture) lifecycle.addObserver(advertisingManage) tvAdvertisingTime = findViewById(R.id.tv_advertising_time) advertisingManage.advertisingManageListener = object : AdvertisingManage.AdvertisingManageListener { override fun timing(second: Int) { tvAdvertisingTime.text = "广告剩余$second秒" advertisingViewModel.millisInFuture = second.toLong() * 1000 } } ... } }
运行程序,当广告剩余2秒的时候,旋转屏幕,打印的日志如图3-4所示。
图3-4 广告剩余2秒时旋转屏幕的日志
从日志中可以看出,广告剩余2秒的时候,由于旋转屏幕停止计时了,因此旋转后会继续从1秒钟开始计时,这与使用onSaveInstanceState方法实现的效果相同。但是从代码中可以很明显地看出,使用ViewModel远比使用onSaveInstanceState简洁,这一切都得益于ViewModel的生命周期。