文章目录
前言:
开始前我们先回答几个问题
1.Jetpack是什么/怎么用?
2.android-sunflower-0.1.6是什么?
问题一:
- Jetpack是什么?
*给出下图:*简单的概括为四大组件库,可以看到他提供的功能还是蛮实用的,没有多余的部分。
- Jetpack怎么用?
这个问题比较大一下说不清楚,我们从接下来的源码分析中,一步一步理解和掌握,有人会说既然做这么多年开发直接看文档不就能行了吗,你说的有道理,但是阅读外文文档学习确实不符合中国国情,这里就涉及到个人以及政治方面的原因了。也可以看到上面的模块之多,不是一日而语的,纸上读来终觉浅,绝知此事要躬行,我们需要慢慢来,我也是第一次在技术迁移上感受到这种焦虑感,Kotlin在Android开发当中的比重越来越大,还在使用JAVA的伙伴赶紧跟上脚步。
问题二:
长征第一步
地址:https://github.com/googlesamples/android-sunflower
--------------------------------------进入正题---------------------------------------
衔接上篇
JetPack控件NavigationUI(基于android-sunflower-0.1.6)
LifeCycles +LiveData
坐标 :PlantDetailFragment
//获取跳转参数,应该在Navigation篇就讲的
val plantId = PlantDetailFragmentArgs.fromBundle(arguments).plantId
//最终获取一个ViewModel 我们先看看PlantDetailViewModel
val factory = InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), plantId)
val plantDetailViewModel = ViewModelProviders.of(this, factory)
.get(PlantDetailViewModel::class.java)
坐标 :PlantDetailViewModel
//按照MVVM的思想,ViewModel就是关联View和Data的,即只处理数据
//有了解过SpringMVC的都知道Repository就是典型的Sql中间件,即处理Data和Sql中间类
class PlantDetailViewModel(
//植物列表
plantRepository: PlantRepository,
//正在种的植物
private val gardenPlantingRepository: GardenPlantingRepository,
private val plantId: String
) : ViewModel() {
//LiveData 理解为一个有生命周期的数据类型
//有种过
val isPlanted: LiveData<Boolean>
val plant: LiveData<Plant>
init {
//看翻译 正在查询或插入中则返回空
/* The getGardenPlantingForPlant method returns a LiveData from querying the database. The
* method can return null in two cases: when the database query is running and if no records
* are found. In these cases isPlanted is false. If a record is found then isPlanted is
* true.
*/
//即查找这个植物
val gardenPlantingForPlant = gardenPlantingRepository.getGardenPlantingForPlant(plantId)
// 下面我们分解来看
isPlanted = Transformations.map(gardenPlantingForPlant) { it != null }
plant = plantRepository.getPlant(plantId)
}
//顾名思义 创建植物到花园
fun addPlantToGarden() {
gardenPlantingRepository.createGardenPlanting(plantId)
}
}
可以看出来Transformations也就是一个转换函数,liveData 可以是任何类型,和Rxjava差不多。
val liveData = Transformations.map(
plant,
object : Function<Plant, Any> {
override fun apply(input: Plant?): Any {
return input != null
}
}
)
坐标:InjectorUtils
fun providePlantDetailViewModelFactory(
context: Context,
plantId: String
): PlantDetailViewModelFactory {
//获取两个数据库中间件 我们看看PlantDetailViewModelFactory
return PlantDetailViewModelFactory(getPlantRepository(context),
getGardenPlantingRepository(context), plantId)
}
坐标:PlantDetailViewModelFactory
class PlantDetailViewModelFactory(
private val plantRepository: PlantRepository,
private val gardenPlantingRepository: GardenPlantingRepository,
private val plantId: String
//最终继承ViewModel
) : ViewModelProvider.NewInstanceFactory() {
//重写方法 泛型T限定为ViewModel和它的子类
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return PlantDetailViewModel(plantRepository, gardenPlantingRepository, plantId) as T
}
}
查看ViewModelProvider源码可知道NewInstanceFactory的create被调用返回泛型Model
viewModel = mFactory.create(modelClass);
回到 :PlantDetailFragment
一个ViewModel的生产
//装备SQL以及其他参数
val factory = InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), plantId)
//get 实例化Model
val plantDetailViewModel = ViewModelProviders.of(this, factory)
.get(PlantDetailViewModel::class.java)
ViewModel的应用
//等同于Databinding的双向绑定
//翻译:没有设置LifecycleOwner,将不会观察LiveData并对其进行更新,不会传播到UI。
setLifecycleOwner(this@PlantDetailFragment)
//简单使用
fab.setOnClickListener { view ->
plantDetailViewModel.addPlantToGarden()
Snackbar.make(view, R.string.added_plant_to_garden, Snackbar.LENGTH_LONG).show()
}
//Observer观察者,不是Rxjava的
plantDetailViewModel.plant.observe(this, Observer { plant ->
shareText = if (plant == null) {
""
} else {
getString(R.string.share_text_plant, plant.name)
}
})
//
//其他写法 onChanged就知道啥意思了,
//也就是ViewModel中 plant = plantRepository.getPlant(plantId)调用后
//onChanged被触发
plantDetailViewModel.plant.observe(this, object : Observer<Plant> {
override fun onChanged(t: Plant?) {
}
})
//简化
plantDetailViewModel.plant.observe(this, Observer<Plant> { })
到这里一个简单ViewModel生成和绑定页面数据操作就完成了
自己操作一下
坐标:AboutFragment
class AboutFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val aboutViewModel = AboutViewModel()
//新写法
val binding = FragmentAboutBinding.inflate(inflater, container, false).apply {
aboutModel = aboutViewModel
setLifecycleOwner(this@AboutFragment)
name.setOnClickListener {
aboutViewModel.name.value = "${aboutViewModel.name.value}${Random(100).nextInt()}"
}
age.setOnClickListener {
aboutViewModel.age.value = Random(100).nextInt()
}
//既然databinding实现了双向绑定功能,这个observe在这方面功能就比较鸡肋
aboutViewModel.name.observe(this@AboutFragment, Observer { name ->
Toast.makeText([email protected](), "${"名字改变$name"}", Toast.LENGTH_SHORT).show()
})
aboutViewModel.age.observe(this@AboutFragment, Observer { age ->
Toast.makeText([email protected](), "${"年纪改变$age"}", Toast.LENGTH_SHORT).show()
})
}
return binding.root
}
}
坐标:AboutViewModel
class AboutViewModel(
var name: MutableLiveData<String> =
MutableLiveData<String>().apply { value = "much" },
var age: MutableLiveData<Int> =
MutableLiveData<Int>().apply { value = 18 }) : ViewModel() {
}
ROOM
https://blog.csdn.net/qq_20330595/article/details/87797828#ROOM_22