Android Weekly Notes #466

Android Weekly Issue #466

Static analysis tools for Android

Android的静态分析工具.

  • Android lint
  • ktlint
  • detekt

各自举了一个例子来说如何自定义规则.

Navigation: Nested graphs and include tag

Navigation graph支持嵌套.

标签.
可以放在一个新的文件中, 再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策略.
  • StateFlowSharedFlow永远都不会停止. 不能指望它们的onCompletionCallback.

还有文中提到了一个观点, 为什么不继续用LiveData呢? 因为LiveData感觉是跟Android相关的一个类, 而SharedFlow和StateFlow是Kotlin的, 这样感觉domain层脱离了对Android的依赖, 更解耦一些.

From Junior to Master in Kotlin — 1 (Basic Syntax)

一些Kotlin的用法.

Code

  • https://github.com/google/modernstorage

News

  • #AndroidDevChallenge - It’s a wrap! Jetpack Compose Challenge的总结, 可以访问获胜者的代码库.

Videos

  • Staying up to date with new technologies as a Mobile Developer
  • Unit Testing Kotlin Channels & Flows
  • Navigation: Navigating between modules

你可能感兴趣的:(Android Weekly Notes #466)