viewModel.gardenPlantings.observe(viewLifecycleOwner, Observer { plantings -> binding.hasPlantings = (plantings != null && plantings.isNotEmpty()) })
这个 Observer 是什么写法呢?真搞不懂,kotlin 感觉太天马行空了,来个大神指教一下,谢谢
1 jinksw 2018-12-24 13:44:34 +08:00 只有一个函数声明的接口可以用 Lambda 代替? 类似 setOnClickListener{ view->xxx } |
![]() | 3 Mystery0 2018-12-24 14:01:54 +08:00 via Android Observer 是一个接口,这个接口里面只有一个函数,所以可以简写成这样 |
![]() | 4 Mystery0 2018-12-24 14:02:24 +08:00 via Android 其实看一下 Observer 的定义应该就清楚了 |
![]() | 6 abbenyyy OP @Mystery0 那为何 ``` val livePlantList = Transformations.switchMap(growZoneNumber) { if (it == NO_GROW_ZONE) { plantRepository.getPlants() } else { plantRepository.getlantsWithGrowZoneNumber(it) } } ``` [源码出处]( https://github.com/googlesamples/android-sunflower/blob/a85cd9b49a924ee2ad029685225d6d071de6bd15/app/src/main/java/com/google/samples/apps/sunflower/viewmodels/PlantListViewModel.kt#L41) Transformations.switchMap 第二个参数也是接口,Transformations.switchMap 的最后一个 lambda 表达式参数移出括号外的方式,并不能套用在 Observer 上面,也就是 ``` viewModel.gardenPlantings.observe(viewLifecycleOwner) { plantings -> binding.hasPlantings = (plantings != null && plantings.isNotEmpty()) } ``` 这个写法并不能编译通过 |
![]() | 7 abbenyyy OP @jinksw 如同我上面说的,如果函数最后一个参数是 lambda 表达式可移出括号外,但是 Observer 如果这样写,编译并不能通过。所以我搞不懂为何有这两种方式 |
![]() | 8 loshine1992 2018-12-24 14:17:33 +08:00 从这个简化的 ```kotlin viewModel.gardenPlantings.observe(viewLifecycleOwner, object : Observer { override fun 方法名(plantings: 参数类型) { binding.hasPlantings = (plantings != null && plantings.isNotEmpty()) } }) ``` 最简化的写法是这样 ```kotlin viewModel.gardenPlantings.observe(viewLifecycleOwner) { binding.hasPlantings = (it!= null && it.isNotEmpty()) } ``` |
9 jinksw 2018-12-24 14:22:33 +08:00 @loshine1992 然而楼主说这样不行 到底是为啥呢 是不是最后一个参数 是泛型类 的缘故 |
![]() | 10 holmesabc 2018-12-24 14:23:04 +08:00 Observer 是个 java 里面的单方法 接口。就能简写 |
![]() | 11 abbenyyy OP @loshine1992 你可以 clone 下来谷歌的 android-sunflower 项目,按照你的方式改写一下,并不能编译通过,我已经试过了 |
12 jinksw 2018-12-24 14:32:23 +08:00 |
![]() | 13 loshine1992 2018-12-24 14:36:32 +08:00 @abbenyyy #2 这个情况下大概率有另外一个方法也接受一个接口的参数, observe(viewLifecycleOwner: A 参数, observer: Observer) observe(viewLifecycleOwner: A 参数, subscriber: Subscriber) 此时需要区分,不能直接用 lambda |
14 jinksw 2018-12-24 14:42:20 +08:00 感觉应该是编译器的锅 我看那个 observer 方法也没有重载 |
![]() | 16 dagger2 2018-12-24 16:56:50 +08:00 viewModel.gardenPlantings.observe 是个 java 方法,接收的参数是一个 Observer 的实现,而不是() -> Unit |
17 pipicat 2018-12-24 17:26:10 +08:00 应该跟泛型有关系。 |
18 pipicat 2018-12-24 17:33:28 +08:00 val a = object : View.OnClickListener { override fun onClick(v: View?) { } } val b = object : Observer<Any>{ override fun onChanged(t: Any?) { } } idea 提示后简化成 val a = View.OnClickListener { } val b = Observer<Any> { } 这里 observer 不加泛型是无法单独声明的。 而 livedata 的这个方法泛型已经确定了,所以 viewModel.gardenPlantings.observe(viewLifecycleOwner, Observer { plantings -> binding.hasPlantings = (plantings != null && plantings.isNotEmpty()) }) 上的泛型没有显式的写出来。 |
19 pipicat 2018-12-24 17:45:33 +08:00 测试了一下 java8 的代码。同样的代码,java8 不用显式写 Observer,但是参数要写出来。 |
![]() | 20 SoloCompany 2018-12-26 23:12:43 +08:00 via iPad java8 的 function interface 和一 kotlin,的 KFunction 并不是同一种类型,需要显式转换,所以需要显式构造 Observer 接口 java8 code 则是类型推断系统自动把 lambda 转换为推断出来的 function interface 也就是说 observer,不需要通过显式的类型转换 |