Android KTX Jake Wharton

Android KTX Jake Wharton

val userLayout :

ViewGroup

= findViewById ( R . id . users )

for

( index in

0

until userLayout . childCount )

{

val view

userLayout . getChildAt ( index )

// Do something with index and view…

}

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} val userLayout :

ViewGroup

= findViewById ( R . id . users )

for

( index in

0

until userLayout . childCount )

{

val view

userLayout . getChildAt ( index )

// Do something with index and view…

} A

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} val userLayout :

ViewGroup

= findViewById ( R . id . users )

for

( index in

0

until userLayout . childCount )

{

val view

userLayout . getChildAt ( index )

// Do something with index and view…

} A

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

for

( index in

0

until userLayout . childCount )

{ G

val view

userLayout . getChildAt ( index )

// Do something with index and view…

} A

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{ G index , view ->

// Do something with index and view…

} A

for ( in 0 until . childCount ) val = userLayout . getChildAt ( index )

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{ G index , view ->

// Do something with index and view…

} A

fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{ G index , view ->

// Do something with index and view…

} A

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{ G index , view ->

// Do something with index and view…

} A

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} D

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{ G index , view ->

// Do something with index and view…

} A

// In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java )

// In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java )

// or all API levels…

val notifications

ContextCompat . getSystemService ( this ,

NotificationManager :: class . java )

// In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java )

// or all API levels…

val notifications

ContextCompat . getSystemService ( this ,

NotificationManager :: class . java ) inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java ) // In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java )

// or all API levels…

val notifications

ContextCompat . getSystemService ( this ,

NotificationManager :: class . java )

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java ) // In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java )

// or all API levels…

val notifications

ContextCompat . getSystemService ( this ,

NotificationManager :: class . java )

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java ) // In an Activity, on API 23+…

val notifications

getSystemService ( NotificationManager :: class . java ) H

// or all API levels…

val notifications

ContextCompat . getSystemService ( this ,

NotificationManager :: class . java )

             	  	   	 	s 

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

// In an Activity…

val notifications

systemService < NotificationManager

() H

               	 	 	 	S 

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

// In an Activity…

val notifications

systemService < NotificationManager

() H

avatarView . setPadding (

10 , avatarView . paddingTop , 10 , avatarView . paddingBottom )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} avatarView.setPadding (

10 , avatarView . paddingTop ,

10 , avatarView . paddingBottom )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} avatarView.setPadding (

10 , avatarView . paddingTop ,

10 , avatarView . paddingBottom )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView.setPadding (

10 , avatarView . paddingTop ,

10 , avatarView . paddingBottom ) R update

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( 10 ,

10 ) R

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( 10 ,

10 ) R

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

val rect

avatarView . clipBounds

val left

rect . left

val top

rect . top

val right

rect . right

val bottom

rect . bottom

// Use left, top, right, bottom…

val rect

avatarView . clipBounds

val left

rect . left

val top

rect . top

val right

rect . right

val bottom

rect . bottom

// Use left, top, right, bottom… inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val rect

avatarView . clipBounds

val left

rect . left

val top

rect . top

val right

rect . right

val bottom

rect . bottom

// Use left, top, right, bottom…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val rect

avatarView . clipBounds

val left

rect . left

val top

rect . top

val right

rect . right

val bottom

rect . bottom

// Use left, top, right, bottom…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val rect

avatarView . clipBounds

val left

rect . left

val T top

rect . top

val R right

rect . right

val B bottom

rect . bottom

// Use left, top, right, bottom…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val

( left , T top , R right , B bottom )

= avatarView . clipBounds

// Use left, top, right, bottom…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val

( left , T top , R right )

= avatarView . clipBounds

// Use left, top, right…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val

( left , T _ , R right )

= avatarView . clipBounds

// Use left, right…

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val

( left , T _ , R right )

= avatarView . clipBounds

// Use left, right…

var

onlyDigits

=

true

for

( c in phoneNumber )

{ A

if

(! c . isDigit ())

{

onlyDigits

=

false

break

} G

} B

val onlyDigits

phoneNumber . all

{ A it . isDigit ()

} B r true for ( c in ) if (! c . ) { onlyDigits = false break } G

val onlyDigits

TextUtils . isDigitsOnly ( phoneNumber ) . all { A it . isDigit () } B

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

TextUtils . isDigitsOnly ( phoneNumber ) L

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

phoneNumber . isDigitsOnly () L

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

phoneNumber .

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

phoneNumber .

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

phoneNumber . is

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

val onlyDigits

phoneNumber . is

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z val onlyDigits

phoneNumber . isDigitsOnly () L

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

core-ktx Android KTX

Android KTX core-ktx Android framework

Android KTX Android framework support-compat core-ktx

Android KTX Android framework core core-ktx

Android KTX Android framework core core-ktx fragment-ktx fragment palette-ktx palette collection-ktx collection lifecycle-reactivestreams-ktx lifecycle-reactivestreams sqlite-ktx sqlite navigation--ktx navigation- work-runtime-ktx work-runtime

Android KTX Android framework core core-ktx fragment-ktx fragment palette-ktx palette collection-ktx collection lifecycle-reactivestreams-ktx lifecycle-reactivestreams sqlite-ktx sqlite navigation--ktx navigation- work-runtime-ktx work-runtime

@RequiresApi ( 26 )

operator

fun

Color . plus ( c :

Color ):

Color

{

val s

if

( colorSpace

!= c . colorSpace ) c . convert ( colorSpace )

else c

val src

s . components

val dst

components

var sa

s . alpha ()

// Destination alpha pre-composited

var da

alpha ()

( 1.0f

sa )

// Index of the alpha component

val ai

componentCount

1

// Final alpha: src_alpha + dst_alpha * (1 - src_alpha)

dst

[ ai ]

= sa + da

// Divide by final alpha to return non pre-multiplied color

if

( dst [ ai ]

0 )

{

    sa /

= dst [ ai ]

    da /

= dst [ ai ]

}

// Composite non-alpha components

for

( i in

0

until ai )

{

    dst

[ i ]

= src [ i ]

sa + dst [ i ]

da

}

return

Color . valueOf ( dst ,

colorSpace )

}

@RequiresApi ( 26 )

operator

fun

Color . plus ( c :

Color ):

Color

{

val s

if

( colorSpace

!= c . colorSpace ) c . convert ( colorSpace )

else c

val src

s . components

val dst

components

var sa

s . alpha ()

// Destination alpha pre-composited

var da

alpha ()

( 1.0f

sa )

// Index of the alpha component

val ai

componentCount

1

// Final alpha: src_alpha + dst_alpha * (1 - src_alpha)

dst

[ ai ]

= sa + da

// Divide by final alpha to return non pre-multiplied color

if

( dst [ ai ]

0 )

{

    sa /

= dst [ ai ]

    da /

= dst [ ai ]

}

// Composite non-alpha components

for

( i in

0

until ai )

{

    dst

[ i ]

= src [ i ]

sa + dst [ i ]

da

}

return

Color . valueOf ( dst ,

colorSpace )

}

@RequiresApi ( 26 )

operator

fun

Color . plus ( c :

Color ):

Color

{

val s

if

( colorSpace

!= c . colorSpace ) c . convert ( colorSpace )

else c

val src

s . components

val dst

components

var sa

s . alpha ()

// Destination alpha pre-composited

var da

alpha ()

( 1.0f

sa )

// Index of the alpha component

val ai

componentCount

1

// Final alpha: src_alpha + dst_alpha * (1 - src_alpha)

dst

[ ai ]

= sa + da

// Divide by final alpha to return non pre-multiplied color

if

( dst [ ai ]

0 )

{

    sa /

= dst [ ai ]

    da /

= dst [ ai ]

}

// Composite non-alpha components

for

( i in

0

until ai )

{

    dst

[ i ]

= src [ i ]

sa + dst [ i ]

da

}

return

Color . valueOf ( dst ,

colorSpace )

}

public

final

class

ColorUtils

{

} Z

public

final

class

ColorUtils

{

@ColorInt

public

static

int compositeColors (

@ColorInt

int foreground ,

@ColorInt

int background )

{

// …

} X

} Z

public

final

class

ColorUtils

{

@ColorInt

public

static

int compositeColors (

@ColorInt

int foreground ,

@ColorInt

int background )

{

// …

} X

@RequiresApi ( 26 )

public

static

Color compositeColors (

Color foreground ,

Color background )

{

// …

} Y

} Z

@RequiresApi ( 26 )

operator

fun

Color . plus ( c :

Color ):

Color

{

val s

if

( colorSpace

!= c . colorSpace ) c . convert ( colorSpace )

else c

val src

s . components

val dst

components

var sa

s . alpha ()

// Destination alpha pre-composited

var da

alpha ()

( 1.0f

sa )

// Index of the alpha component

val ai

componentCount

1

// Final alpha: src_alpha + dst_alpha * (1 - src_alpha)

dst

[ ai ]

= sa + da

// Divide by final alpha to return non pre-multiplied color

if

( dst [ ai ]

0 )

{

    sa /

= dst [ ai ]

    da /

= dst [ ai ]

}

// Composite non-alpha components

for

( i in

0

until ai )

{

    dst

[ i ]

= src [ i ]

sa + dst [ i ]

da

}

return

Color . valueOf ( dst ,

colorSpace )

}

@RequiresApi ( 26 )

inline operator

fun

Color . plus ( c :

Color ):

Color

=

ColorUtils . compositeColors ( c ,

this )

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

KTX Principles

KTX Principles Adapt existing functionality and redirect features upstream

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z

operator

fun

ViewGroup . iterator ()

=

object

:

MutableIterator < View

{

private

var

index

=

0

override

fun hasNext ()

=

index

<

childCount

override

fun next ()

=

getChildAt ( index ++)

?:

throw

IndexOutOfBoundsException ()

override

fun remove ()

= removeViewAt (-- index )

}

operator

fun

ViewGroup . iterator ()

=

object

:

MutableIterator < View

{

private

var

index

=

0

override

fun hasNext ()

=

index

<

childCount

override

fun next ()

=

getChildAt ( index ++)

?:

throw

IndexOutOfBoundsException ()

override

fun remove ()

= removeViewAt (-- index )

} for

( view in userLayout )

{

// Do something with view…

}

operator

fun

ViewGroup . iterator ()

=

object

:

MutableIterator < View

{

private

var

index

=

0

override

fun hasNext ()

=

index

<

childCount

override

fun next ()

=

getChildAt ( index ++)

?:

throw

IndexOutOfBoundsException ()

override

fun remove ()

= removeViewAt (-- index )

} for

( view in userLayout )

{

// Do something with view…

}

operator

fun

ViewGroup . iterator ()

=

object

:

MutableIterator < View

{

private

var

index

=

0

override

fun hasNext ()

=

index

<

childCount

override

fun next ()

=

getChildAt ( index ++)

?:

throw

IndexOutOfBoundsException ()

override

fun remove ()

= removeViewAt (-- index )

} for

( view in userLayout )

{

// Do something with view…

}

KTX Principles Adapt existing functionality and redirect features upstream

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive

inline fun

ViewGroup . forEachIndexed ( action :

( Int , View )

->

Unit )

{

for

( index in

0

until

childCount )

{

    action

( index , getChildAt ( index ))

} Z

} Z

val userLayout :

ViewGroup

= findViewById ( R . id . users )

userLayout . forEachIndexed

{

index , view ->

// Do something with index and view…

} A

inline

fun

< reified T

Context . systemService ()

=

ContextCompat . getSystemService ( this , T :: class . java )

// In an Activity…

val notifications

systemService < NotificationManager

() H

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

inline operator

fun

Rect . component1 ()

=

left

inline operator

fun

Rect . component2 ()

=

top

inline operator

fun

Rect . component3 ()

=

right

inline operator

fun

Rect . component4 ()

=

bottom

val

( left , T _ , R right )

= avatarView . clipBounds

// Use left, right…

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this ) Z val onlyDigits

phoneNumber . isDigitsOnly () L

operator

fun

ViewGroup . iterator ()

=

object

:

MutableIterator < View

{

private

var

index

=

0

override

fun hasNext ()

=

index

<

childCount

override

fun next ()

=

getChildAt ( index ++)

?:

throw

IndexOutOfBoundsException ()

override

fun remove ()

= removeViewAt (-- index )

} for

( view in userLayout )

{

// Do something with view…

}

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive Leverage features unique to Kotlin

view . setOnClickListener {

// React to click…

} Z

fun

View . click ( listener :

( View )

->

Unit )

{

setOnClickListener

( listener )

} Y

view . setOnClickListener { P

// React to click…

} Z

fun

View . click ( listener :

( View )

->

Unit )

{

setOnClickListener

( listener )

} Y

view . setOnClickListener { P

// React to click…

} Z

c

fun

View . click ( listener :

( View )

->

Unit )

{

setOnClickListener

( listener )

} Y

view . click

{ P

// React to click…

} Z C

view . click

{ P

// React to click…

} Z view . setOnClickListener {

// React to click…

}

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive Leverage features unique to Kotlin

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive Leverage features unique to Kotlin Code golf APIs to be as short as possible

if

( Build . VERSION . SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

inline

fun onApi ( level :

Int , body :

()

->

Unit )

{

if

( Build . VERSION . SDK_INT

= level )

{

    body

()

} Z

}

if

( Build . VERSION . SDK_INT

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

inline

fun onApi ( level :

Int , body :

()

->

Unit )

{

if

( Build . VERSION . SDK_INT

= level )

{

    body

()

} Z

} Q

if

( Build . VERSION . SDK_INT

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z onApi

inline

fun onApi ( level :

Int , body :

()

->

Unit )

{

if

( Build . VERSION . SDK_INT

= level )

{

    body

()

} Z

} Q

onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z if

( Build . VERSION . SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

if

( SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

if

( SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

if

( SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z else { // Something …

}

onApi ( 19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z

if

( SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z else { // Something …

} L onApi ( 19 ) F { A

TransitionManager . beginDelayedTransition ( viewGroup )

} ,

if

( SDK_INT

=

19 )

{

TransitionManager . beginDelayedTransition ( viewGroup )

} Z else { // Something …

} L onApi ( 19 ,

{ A

TransitionManager . beginDelayedTransition ( viewGroup )

}, { T

// Something

…

}) F

if

( SDK_INT

=

28 )

{ // Fancy new thing …

}

else if ( SDK_INT

= 19 ) {

TransitionManager . beginDelayedTransition ( viewGroup )

} Z else { // Something …

} L onApi ( 19 ,

{ A

TransitionManager . beginDelayedTransition ( viewGroup )

}, Z { T

// Something

…

}) F

if

( SDK_INT

=

28 )

{ // Fancy new thing …

}

else if ( SDK_INT

= 19 ) {

TransitionManager . beginDelayedTransition ( viewGroup )

} Z else { // Something …

} L onApi ( 19 ,

{ A

TransitionManager . beginDelayedTransition ( viewGroup )

}, Z { T

// Something

…

}) F

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive Leverage features unique to Kotlin Code golf APIs to be as short as possible

KTX Principles Adapt existing functionality and redirect features upstream Default to inline unless code size or allocation is prohibitive Leverage features unique to Kotlin Code golf APIs to be as short as possible Optimize for a single and/or specific use case

Android KTX Android framework core core-ktx fragment-ktx fragment palette-ktx palette collection-ktx collection lifecycle-reactivestreams-ktx lifecycle-reactivestreams sqlite-ktx sqlite navigation--ktx navigation- work-runtime-ktx work-runtime

Android KTX Android framework core core-ktx fragment-ktx fragment palette-ktx palette collection-ktx collection lifecycle-reactivestreams-ktx lifecycle-reactivestreams sqlite-ktx sqlite navigation--ktx navigation- work-runtime-ktx work-runtime

supportFragmentManager . beginTransaction ()

. replace ( android . R . id . content , userFragment )

. commit ()

inline

fun

FragmentManager . transaction (

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

transaction

. commit ()

} supportFragmentManager . beginTransaction ()

. replace ( android . R . id . content , userFragment )

. commit ()

inline

fun

FragmentManager . transaction (

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

transaction

. commit ()

} A

supportFragmentManager . beginTransaction ()

. replace ( android . R . id . content , userFragment )

t

. commit ()

inline

fun

FragmentManager . transaction (

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

transaction

. commit ()

} A

supportFragmentManager . transaction {

replace

( android . R . id . content , userFragment )

} Z

T

inline

fun

FragmentManager . transaction (

allowStateLoss

:

Boolean

=

false

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

if

( allowStateLoss ) transaction . commitAllowingStateLoss ()

else transaction . commit ()

} A

supportFragmentManager . transaction {

replace

( android . R . id . content , userFragment )

} Z

inline

fun

FragmentManager . transaction (

allowStateLoss

:

Boolean

=

false

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

if

( allowStateLoss ) transaction . commitAllowingStateLoss ()

else transaction . commit ()

} A

supportFragmentManager . transaction { G

replace

( android . R . id . content , userFragment )

} Z

inline

fun

FragmentManager . transaction (

allowStateLoss

:

Boolean

=

false ,

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

if

( allowStateLoss ) transaction . commitAllowingStateLoss ()

else transaction . commit ()

} A

supportFragmentManager . transaction ( allowStateLoss

=

true )

{ G

replace

( android . R . id . content , userFragment )

} Z

L7
ALOAD

3

INVOKEVIRTUAL androidx/fragment/app/ FragmentManager beginTransaction()

Landroidx/fragment/app/ FragmentTransaction ;

ASTORE

7 L8
ALOAD

7

LDC

16908290

ALOAD

2

INVOKEVIRTUAL

androidx/fragment/app/ FragmentTransaction replace( I Landroidx/fragment/app/ Fragment ; )

Landroidx/fragment/app/ FragmentTransaction ;

POP

L9
ALOAD

7

INVOKEVIRTUAL androidx/fragment/app/ FragmentTransaction

     commitAllowingStateLoss() 
     I 
 

POP

inline

fun

FragmentManager . transaction (

allowStateLoss

:

Boolean

=

false ,

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

if

( allowStateLoss ) transaction . commitAllowingStateLoss ()

else transaction . commit ()

} A

supportFragmentManager . transaction ( allowStateLoss

=

true )

{ G

replace

( android . R . id . content , userFragment )

} Z

inline

fun

FragmentManager . transaction (

now

:

Boolean

=

false ,

allowStateLoss

:

Boolean

=

false ,

body

:

FragmentTransaction .()

->

Unit

)

{

val transaction

beginTransaction ()

transaction

. body ()

if

( now )

{

if

( allowStateLoss ) transaction . commitNowAllowingStateLoss ()

else transaction . commitNow ()

}

else

{

if

( allowStateLoss ) transaction . commitAllowingStateLoss ()

else transaction . commit ()

}

} A

Building Kotlin-friendly libraries

Building Kotlin-friendly libraries • Port public API or entire library to Kotlin

Building Kotlin-friendly libraries • Port public API or entire library to Kotlin

• Ship sibling artifact with Kotlin extensions

Building Kotlin-friendly libraries • Port public API or entire library to Kotlin

• Ship sibling artifact with Kotlin extensions

• ???

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

static

boolean isDigitsOnly ( CharSequence str )

{

int len

str . length ();

// …

} Y

} Z

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

@ExtensionFunction

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

@ExtensionFunction

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z

inline

fun

CharSequence . isDigitsOnly ()

=

TextUtils . isDigitsOnly ( this )

val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

@ExtensionFunction

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

@ExtensionFunction

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z val onlyDigits

phoneNumber . isDigitsOnly ()

class

TextUtils

{

@ExtensionFunction

static

boolean isDigitsOnly ( @NonNull

CharSequence str )

{

int len

str . length ();

// …

} Y

} Z val onlyDigits

phoneNumber . isDigitsOnly () // in the bytecode we get val

onlyDigits

TextUtils . isDigitsOnly ( phoneNumber )

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

class

View

{

void setPadding ( int left ,

int top ,

int right ,

int bottom )

{ /* … */ } B

} A

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

avatarView. updatePadding ( left

10 , right

10 ) R

class

View

{

void setPadding (

@KtName ( "left" ) A int left ,

@KtName ( "top" ) A int top ,

@KtName ( "right" ) A int right ,

@KtName ( "bottom" ) A int bottom

)

{

/* … */ } B

} A

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

class

View

{

void setPadding (

@KtName ( "left" ) A @DefaultValue ( "paddingLeft" ) int left ,

@KtName ( "top" ) A @DefaultValue ( "paddingTop" ) int top ,

@KtName ( "right" ) A @DefaultValue ( "paddingRight" ) int right ,

@KtName ( "bottom" ) A @DefaultValue ( "paddingBottom" ) int bottom

)

{

/* … */ } B

} A

inline

fun

View . updatePadding (

left

:

Int

=

paddingLeft ,

top

:

Int

=

paddingTop ,

right

:

Int

=

paddingRight ,

bottom

:

Int

=

paddingBottom

)

{

setPadding

( left , top , right , bottom )

} A

class

View

{

void setPadding (

@KtName ( "left" ) @DefaultValue ( "paddingLeft" ) int left ,

@KtName ( "top" ) @DefaultValue ( "paddingTop" ) int top ,

@KtName ( "right" ) @DefaultValue ( "paddingRight" ) int right ,

@KtName ( "bottom" ) @DefaultValue ( "paddingBottom" ) int bottom

)

{

/* … */ } B

} A

avatarView. updatePadding ( left

10 , right

10 ) R

class

View

{

void setPadding (

@KtName ( "left" ) @DefaultValue ( "paddingLeft" ) int left ,

@KtName ( "top" ) @DefaultValue ( "paddingTop" ) int top ,

@KtName ( "right" ) @DefaultValue ( "paddingRight" ) int right ,

@KtName ( "bottom" ) @DefaultValue ( "paddingBottom" ) int bottom

)

{

/* … */ } B

} A

avatarView.setPadding ( left

10 , right

10 ) R

update

class

View

{

void setPadding (

@KtName ( "left" ) @DefaultValue ( "paddingLeft" ) int left ,

@KtName ( "top" ) @DefaultValue ( "paddingTop" ) int top ,

@KtName ( "right" ) @DefaultValue ( "paddingRight" ) int right ,

@KtName ( "bottom" ) @DefaultValue ( "paddingBottom" ) int bottom

)

{

/* … */ } B

} A

avatarView.setPadding ( left

10 , right

10 ) R // in bytecode we get avatarView . setPadding (

10 , avatarView . paddingTop , 10 , avatarView . paddingBottom )

update

KEEP-110

KEEP-110 • @ExtensionFunction / @ExtensionProperty — Turn a static method with at least one argument into an extension function or an extension property.

KEEP-110 • @ExtensionFunction / @ExtensionProperty — Turn a static method with at least one argument into an extension function or an extension property. • 
 
 • @DefaultValue — Default parameter values.

KEEP-110 • @ExtensionFunction / @ExtensionProperty — Turn a static method with at least one argument into an extension function or an extension property. • 
 
 • @DefaultValue — Default parameter values. • 
 
 • @KtName — An alternate name for methods, fields, and parameters for use by Kotlin code.

Building Kotlin-friendly libraries • Port public API or entire library to Kotlin

• Ship sibling artifact with Kotlin extensions

• ???

Building Kotlin-friendly libraries • Port public API or entire library to Kotlin

• Ship sibling artifact with Kotlin extensions

• KEEP-110 annotations

Android KTX Android framework core core-ktx fragment-ktx fragment palette-ktx palette collection-ktx collection lifecycle-reactivestreams-ktx lifecycle-reactivestreams sqlite-ktx sqlite navigation--ktx navigation- work-runtime-ktx work-runtime

https://github.com/Kotlin/KEEP/issues/110

Jake Wharton Thank you

@JakeWharton