Android Weekly Notes #466
2021-07-11 本文已影响0人
圣骑士wind
Android Weekly Issue #466
Static analysis tools for Android
Android的静态分析工具.
- Android lint
- ktlint
- detekt
各自举了一个例子来说如何自定义规则.
Navigation: Nested graphs and include tag
Navigation graph支持嵌套.
<navigation>
标签.
可以放在一个新的文件中, 再include进来.
这样就可以跨module组织代码了.
Avoid CI/CD Lock-in — Make Your Builds More Portable
让CI更具可移植性.
- 把脚本放在代码库里.
- 把gradle任务放在shell脚本里.
- 尽量使用gradle插件而不是ci插件.
- 使用容器化技术.
- 最小化在ci上的配置.
Assisted Injection With Dagger and Hilt
对于构造一个对象, 有些参数需要DI容器帮忙, 有些参数你想自己提供的情况.
- 解决方案1: 添加AutoFactory依赖, 和daggeer结合使用, 会生成一个工厂.
- 解决方案2: dagger2.31+之后, 使用
@AssistedInject
注解, 标记在构造函数上, 想要手动提供的参数, 标记@Assisted
. 使用@AssistedFactory
创建一个工厂.
对ViewModel来说, 还需要提供一个ViewModelProvider.Factory
的实现.
Dagger 2 and Jetpack Compose Integration
Dagger2和Jetpack Compose的集成.
首先, 开篇定义navigation, 假定每个屏幕需要一个ViewModel:
setContent {
val navController = rememberNavController()
NavHost(navController, startDestination = NavigationDestination.Screen1.destination) {
composable(NavigationDestination.Screen1.destination) {
val viewModel: Screen1ViewModel = viewModel()
Screen1(viewModel = viewModel)
}
composable(NavigationDestination.Screen2.destination) {
val viewModel: Screen2ViewModel = viewModel()
Screen2(viewModel = viewModel)
}
}
}
后来, 换成这种:
composable(NavigationDestination.Screen1.destination) {
val viewModel: Screen1ViewModel = hiltNavGraphViewModel()
Screen1(viewModel = viewModel)
}
hiltNavGraphViewModel()
做了什么呢?
- 找ViewModel的owner: Hilt用了
LocalViewModelStoreOwner
, 可以是Activity, Fragment, 在composable中, 是NavBackStackEntry
.
了解Hilt怎么做之后, 看看Dagger 2.
setContent {
val navController = rememberNavController()
NavHost(navController, startDestination = NavigationDestination.Screen1.destination) {
composable(NavigationDestination.Screen1.destination) {
// option #1 create a component inside NavBackStackEntry,
// which can be helpful if we need to provide more than one object from DI here
val component = DaggerScreen1Component.builder().build()
val viewModel: Screen1ViewModel = daggerViewModel {
component.getViewModel()
}
Screen1(viewModel = viewModel)
}
composable(NavigationDestination.Screen2.destination) {
val viewModel: Screen2ViewModel = daggerViewModel {
// option #2 create DI component and instantly get ViewModel instance
DaggerScreen2Component.builder().build().getViewModel()
}
Screen2(viewModel = viewModel)
}
}
}
Infinite auto-scrolling lists with RecyclerView & LazyLists in Compose
无限自动滚动的list, 有点像走马灯的效果.
Kotlin SharedFlow or: How I learned to stop using RxJava and love the Flow
- RxJava后台任务分步骤进行UI显示 -> Flow.
- 处理热流:
- PublishSubject -> SharedFlow.
- BehaviorSubject -> StateFlow.
一些特点:
-
StateFlow
是conflated: 如果新的值和旧的值一样, 不会传播. -
SharedFlow
需要合理设置buffer和replay策略. -
StateFlow
和SharedFlow
永远都不会停止. 不能指望它们的onCompletionCallback
.
还有文中提到了一个观点, 为什么不继续用LiveData呢? 因为LiveData感觉是跟Android相关的一个类, 而SharedFlow和StateFlow是Kotlin的, 这样感觉domain层脱离了对Android的依赖, 更解耦一些.
From Junior to Master in Kotlin — 1 (Basic Syntax)
一些Kotlin的用法.
Code
News
- #AndroidDevChallenge - It’s a wrap! Jetpack Compose Challenge的总结, 可以访问获胜者的代码库.