androidkotlinlambdaandroid-datepicker

Why I could use a lambda to define onDateChangedListener(an interface), and where the data comes from?


I am using DatePicker(a widget), and I use .init() with it .init() need four things.

open fun init( year: Int,  
   monthOfYear: Int,    
   dayOfMonth: Int,   
   onDateChangedListener: DatePicker.OnDateChangedListener! ): Unit

and I can code like this

val datepicker = findViewById<DatePicker>(R.id.date_Picker)
val today =Calendar.getInstance()
datepicker.init(today.get(Calendar.YEAR),today.get(Calendar.MONTH),
                today.get(Calendar.DAY_OF_MONTH))
                {view,year,month,day->
                // things it do when the date is changed
                }

why I can write like this? to just give a lambda? and where the "view","year","month",and "day"comes from? how does this lambda reads what date I choose and pass it to the lambda?


Solution

  • Because the Kotlin language is smart under the hood. If there is an interface with only a single function, you can pass in a lambda instead and behind the scenes it will generate a class that derives from that interface and calls your lambda in that single function.

    So

        datepicker.init(today.get(Calendar.YEAR),today.get(Calendar.MONTH),
                    today.get(Calendar.DAY_OF_MONTH))
                    {view,year,month,day->
                    // things it do when the date is changed
                    }
        
    

    becomes:

       class MyListener: DatePicker.OnDateChangedListener {
          override fun onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
             //body of your lambda
          }
        }
    
       datepicker.init(today.get(Calendar.YEAR),today.get(Calendar.MONTH),
                today.get(Calendar.DAY_OF_MONTH), 
                MyListener()
       )
        
    

    This only works if the type is an interface with a single function. If there are two functions, it won't know which one to override so it will fail to compile.

    The parameters to the lambda are just the normal values passed in when the lambda is called. You can call them whatever you want, but their type and number are determined by the interface you're implementing.