Search code examples
androidkotlinandroid-lifecycle

Result of obj.apply{ func1() } is different than obj.func1()


In kotlin, apply{} is defined as inline fun <T> T.apply(block: T.() -> Unit): T
I thought the use of this function is to minimize this code

obj.func1()
obj.func2()
obj.func3()
...

to

obj.apply {
    func1()
    func2()
    func3()
}

But now I think it has some totally different actual use case. In my android studio project, i got this log

2020-12-08 13:3:22.648 28006-28006/com.skb.skara D/VideoViewActivity: onStart: pos 2677
2020-12-08 13:3:22.649 28006-28006/com.skb.skara D/VideoViewActivity: initializePlayer: seeked to 0
2020-12-08 13:3:22.650 28006-28006/com.skb.skara D/VideoViewActivity: onStart: pos 2677

for this code

private var currentPosition: Int

override fun onStart() {
    super.onStart()
    Log.d(TAG, "onStart: pos $currentPosition")
    initializePlayer()
    Log.d(TAG, "onStart: pos $currentPosition")
    if (currentPosition == 0) {
        Log.d(TAG, "onStart: vid start")
        fullscreen_video.start()
    }
    show()
}

private fun initializePlayer() {
    fullscreen_video.apply {
        setVideoPath(videoUrl)
        seekTo(currentPosition)
        Log.d(TAG, "initializePlayer: seeked to $currentPosition")
    }
}

Then I changed initialisePlayer function to this

private fun initializePlayer() {
    fullscreen_video.setVideoPath(videoUrl)
    fullscreen_video.seekTo(currentPosition)
    Log.d(TAG, "initializePlayer: seeked to $currentPosition")
}

and then I got this log

2020-12-08 13:12:53.548 28006-28006/com.skb.skara D/VideoViewActivity: onStart: 2677
2020-12-08 13:12:53.550 28006-28006/com.skb.skara D/VideoViewActivity: initializePlayer: seeked to 2677
2020-12-08 13:12:53.550 28006-28006/com.skb.skara D/VideoViewActivity: onStart: 2677

Someone please explain this behaviour and also explain the use of scope function apply{}


Solution

  • Be careful, VideoView has its own currentPosition. Accessing currentPosition inside its apply block will get the currentPosition of the VideoView.

    private fun initializePlayer() {
        fullscreen_video.apply {
            setVideoPath(videoUrl)
            seekTo(currentPosition) // This will use VideoView.currentPosition
            Log.d(TAG, "initializePlayer: seeked to $currentPosition") // This, too
        }
    }
    

    Explain about apply:

    The context object is available as a receiver (this). And this always can be omitted.

    If you want to access the currentPosition you declared above, use this@YourActivity.currentPosition. Replace YourActivity with your activity.