首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

有懂 kotlin 的么,想请教一个函数为 lambda 表达式的写法的出处。

  •  
  •   abbenyyy · 351 天前 · 1501 次点击
    这是一个创建于 351 天前的主题,其中的信息可能已经有所发展或是发生改变。
    viewModel.gardenPlantings.observe(viewLifecycleOwner, Observer { plantings ->
           binding.hasPlantings = (plantings != null && plantings.isNotEmpty())
    })
    

    源码出处

    这个 Observer 是什么写法呢?真搞不懂,kotlin 感觉太天马行空了,来个大神指教一下,谢谢

    20 回复  |  直到 2018-12-26 23:12:43 +08:00
        1
    jinksw   351 天前
    只有一个函数声明的接口可以用 Lambda 代替?

    类似 setOnClickListener{
    view->xxx
    }
        2
    abbenyyy   351 天前
    @jinksw 这个我知道,谷歌的这个为何要在前面加上 Observer 呢
        3
    Mystery0   351 天前 via Android
    Observer 是一个接口,这个接口里面只有一个函数,所以可以简写成这样
        4
    Mystery0   351 天前 via Android
    其实看一下 Observer 的定义应该就清楚了
        5
    jinksw   351 天前
    @abbenyyy 不加那个 Observer 应该也可以 只是指出类型了
        6
    abbenyyy   351 天前
    @Mystery0 那为何
    ```
    val livePlantList = Transformations.switchMap(growZoneNumber) {
    if (it == NO_GROW_ZONE) {
    plantRepository.getPlants()
    } else {
    plantRepository.getPlantsWithGrowZoneNumber(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   351 天前
    @jinksw 如同我上面说的,如果函数最后一个参数是 lambda 表达式可移出括号外,但是 Observer 如果这样写,编译并不能通过。所以我搞不懂为何有这两种方式
        8
    loshine1992   351 天前
    从这个简化的

    ```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   351 天前
    @loshine1992 然而楼主说这样不行
    🤔 到底是为啥呢 是不是最后一个参数 是泛型类 的缘故
        10
    holmesabc   351 天前
    Observer 是个 java 里面的单方法 接口。就能简写
        11
    abbenyyy   351 天前
    @loshine1992 你可以 clone 下来谷歌的 android-sunflower 项目,按照你的方式改写一下,并不能编译通过,我已经试过了
        12
    jinksw   351 天前
        13
    loshine1992   351 天前
    @abbenyyy #2 这个情况下大概率有另外一个方法也接受一个接口的参数,

    observe(viewLifecycleOwner: A 参数, observer: Observer)
    observe(viewLifecycleOwner: A 参数, subscriber: Subscriber)

    此时需要区分,不能直接用 lambda
        14
    jinksw   351 天前
    感觉应该是编译器的锅 我看那个 observer 方法也没有重载
        15
    abbenyyy   351 天前
    @jinksw 好像是因为 observer 方法有一个通配符泛型<? super T>,所以才需要明确泛型吧
        16
    dagger2   351 天前
    viewModel.gardenPlantings.observe 是个 java 方法,接收的参数是一个 Observer 的实现,而不是() -> Unit
        17
    pipicat   351 天前
    应该跟泛型有关系。
        18
    pipicat   351 天前
    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   351 天前
    测试了一下 java8 的代码。同样的代码,java8 不用显式写 Observer,但是参数要写出来。
        20
    SoloCompany   349 天前 via iPad
    java8 的 function interface 和一 kotlin,的 KFunction 并不是同一种类型,需要显式转换,所以需要显式构造 Observer 接口
    java8 code 则是类型推断系统自动把 lambda 转换为推断出来的 function interface 也就是说 observer,不需要通过显式的类型转换
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2176 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 23ms · UTC 15:50 · PVG 23:50 · LAX 07:50 · JFK 10:50
    ♥ Do have faith in what you're doing.