Jetpack
什么是Jetpack
Jetpack是一个由多个库组成的套件,可帮助开发者遵循最佳做法,减少样板代码并编写可在各种Android版本和设备中一致运行的代码
- 遵循最佳做法
- 消除样板代码
- 减少不一致
LifeCycle
解耦问题:减少系统组件(Activity等)与用户自定义组件的耦合程度
让类能轻松感知到Activity的声明周期的同时不需要在Activity中编写大量逻辑代码
用法
- 新建类,实现LifecycleObserve接口
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun activityStart(){
Log.d("MyObserver","activityStart")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun activityStop(){
Log.d("MyObserver","activityStop")
}
}
- 可以看到,我们在方法使用了@OnLifecycleEvent注解,并传入了一种生命周期事件。生命周期事件的类型共7种:ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP、ON_DESTROY分别匹配Activity中相应的生命周期回调;其次关于ON_ANY类型,表示可以匹配Activity的任何生命周期回调。
- Activity中调用
override fun onCreate (savedInstanceState: Bundle?) {
super.onCreate (savedInstanceState)
setContentView (R.layout.activity_main)
...
lifecycle.addObserver (MyObserver())
}
- lifecycle.currentState 主动获取当前的生命周期状态,其返回类型是个枚举(INITIALIZED、DESTROYED、CREATED、STARTED、RESUMED这5种状态类型)
ViewModel
缓存状态,可在配置更改后持久保留响应状态,这意味着在Activity之间导航时或进行配置更改后(例如旋转屏幕时),界面将无需重新提取数据。
优势
- 允许持久保留界面状态
- 提供对业务逻辑的访问权限
用法
- 创建自己的viewModel
class MainViewModel : ViewModel () {
var counter = 0
}
- Activity中实例化viewModel
class MainActivity : AppCompatActivity () {
lateinit var viewModel : MainViewModel
override fun onCreate (savedInstanceState : Bundle?) {
super.onCreate (savedInstanceState)
setContentView (R.layout.activity.main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
plusOneBtn.setOnClickListener {
viewModel.counter++
refreshCounter()
}
refreshCounter()
}
private fun refreshCounter() {
infoText.text = viewModel.counter.toString()
}
}
目前推荐写法:
model = ViewModelProvider(this)[MyViewModel::class.java]
向ViewModel传值
- 新建类 实现ViewModelProvider.Factory的接口
新建类 实现ViewModelProvider.Factory的接口
class MainViewModelFactory(private val countReserved: Int): ViewModelProvider.Factory {
// create方法执行时机和Activity的生命周期无关
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MyViewModel(countReserved) as T
}
}
- 修改MyViewModel
//增加传入参数 countReserved
class MyViewModel(countReserved: Int):ViewModel (){
var counter = countReserved
}
- Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
// private val model: MyViewModel by ViewModels()
private lateinit var model: MyViewModel
private lateinit var sp: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
sp = getPreferences(Context.MODE_PRIVATE)
val countReserved = sp.getInt("count_reserved",0)
// 增加参数 MainViewModelFactory 将countReserved 传给MainViewModelFactory 的构造函数
model = ViewModelProvider(this,
MainViewModelFactory(countReserved))[MyViewModel::class.java]
binding.apply {
btnAdd.setOnClickListener {
model.counter++
refreshCounter()
}
clearBtn.setOnClickListener{
model.counter = 0
refreshCounter()
}
}
refreshCounter()
}
// 对counter 进行保存
override fun onPause() {
super.onPause()
sp.edit {
putInt("count_reserved",model.counter)
}
}
private fun refreshCounter() {
binding.textView.text = model.counter.toString()
}
}
ViewModel生命周期
LiveData
LiveData 是Jetpact提供的一种响应式编程组件
主要用于UI组件的数据绑定 当LiveData持有的数据发生变化时,所有已注册的观察者都会自动收到通知 使得UI可以自动响应数据变化
MutableLiveData 是一种可变的LiveData 有三种读写数据的方法:getValue()、setValue()和postValue() 其中postValue用于非主线程给LiveData设置数据
用法
- 推荐写法:永远只暴露不可变的LiveData给外部
class MyViewModel(countReserved: Int):ViewModel (){
// 使用LiveData改造
// counter 为不可变 LiveData
val counter: LiveData<Int>
get() = _counter
// _counter对外部 不可见
private val _counter = MutableLiveData<Int>()
init {
_counter.value = countReserved
}
fun plusone(){
val count = counter.value ?: 0
_counter.value = count + 1
}
fun clear(){
_counter.value = 0
}
}
- Activity中调用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("MainActivity1", "onCreate")
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycle.addObserver(MyObserver())
sp = getPreferences(Context.MODE_PRIVATE)
val countReserved = sp.getInt("count_reserved", 0)
// 增加参数 MainViewModelFactory 将countReserved 传给MainViewModelFactory 的构造函数
model =
ViewModelProvider(this, MainViewModelFactory(countReserved))[MyViewModel::class.java]
binding.apply {
btnAdd.setOnClickListener {
model.plusone()
}
clearBtn.setOnClickListener {
model.clear()
}
model.counter.observe(this@MainActivity){ count ->
textView.text = count.toString()
}
}
}
map和swichMap方法
- map:将实际包含数据的LiveData和仅用于观察数据的LiveData进行转换
- switchMap:viewmodel中的某个LiveData对象是调用另外的方法获取的,可以使用SwitchMap,将该对象转换成可观察的LiveData对象