Kotlin, why?
Pawel Byszewski
1
What is the talk
about?
Only necessary
Syntax
Code
patterns
Facts and
analysis
kotlin.com
kotlin.com
kotlin.com
kotlin.com
Syntax
10
class Conference(var name: String,
val startDate: Calendar,
val endDate: Calendar)
class Conference2(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
get() = "prefix_$field"
set(value) {
field = "${value}_sufix"
}
}
Getters and setters
class Conference(var name: String,
val startDate: Calendar,
val endDate: Calendar)
class Conference2(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
get() = "prefix_$field"
set(value) {
field = "${value}_sufix"
}
}
Getters and setters
val - finalvar - not final
class Conference(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
}
Getters and setters
val - finalvar - not final
class Conference(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
get() = "prefix_$field"
}
Getters and setters
“prefix” + field
val - finalvar - not final
class Conference(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
get() = "prefix_$field"
}
Getters and setters
“prefix” + field
val - finalvar - not final
field - backing field
for property
class Conference(name: String,
val startDate: Calendar,
val endDate: Calendar) {
var name: String = name
get() = "prefix_$field"
set(value) {
field = "${value}_sufix"
}
}
Getters and setters
“prefix” + field
val - finalvar - not final
field - backing field
for property
Getters and setters
Lombok
Getters and setters
class Conference(val name: String,
val startDate: Calendar,
val endDate: Calendar) {
val passed: Boolean
get() = Calendar.getInstance().after(endDate)
}
It is property like in
C#, not java field
Getters and setters
class Conference(val name: String,
val startDate: Calendar,
val endDate: Calendar) {
val passed: Boolean
get() = Calendar.getInstance().after(endDate)
}
It doesn’t exist
It is property like in
C#, not java field
Constructor
class Conference(val name: String,
val city: String)
fun test() {
val conference = Conference("Confitura", "Warsaw")
}
Constructor
Lombok
Constructor
class Conference(val name: String,
val city: String,
val isFree: Boolean)
fun test() {
val conference = Conference("Confitura", "Warsaw")
}
Constructor
class Conference(val name: String,
val city: String,
val isFree: Boolean = false)
fun test() {
val conference = Conference("Confitura", "Warsaw")
}
public Conference(@NotNull String name,
@NotNull String city,
boolean isFree) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(city, "city");
this.name = name;
this.city = city;
this.isFree = isFree;
}
Constructor
One to rulethem all
public Conference(@NotNull String name,
@NotNull String city,
boolean isFree) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(city, "city");
this.name = name;
this.city = city;
this.isFree = isFree;
}
Constructor
val conference
= Conference("Confitura", "Warsaw")
One to rulethem all
public Conference(@NotNull String name,
@NotNull String city,
boolean isFree) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(city, "city");
this.name = name;
this.city = city;
this.isFree = isFree;
}
Constructor
public static final void test() {
Conference conference
= new Conference("Confitura", "Warsaw", false);
}
val conference
= Conference("Confitura", "Warsaw")
One to rulethem all
class Conference(val name: String,
val startDate: Calendar,
val endDate: Calendar)
fun test() {
val conference1 = Conference("Confitura",
Calendar.getInstance(),
Calendar.getInstance())
val conference2 = Conference(name = "Confitura",
startDate = Calendar.getInstance(),
endDate = Calendar.getInstance())
}
Constructor
class Conference(val name: String,
val startDate: Calendar,
val endDate: Calendar)
fun test() {
val conference1 = Conference("Confitura",
Calendar.getInstance(),
Calendar.getInstance())
val conference2 = Conference(name = "Confitura",
startDate = Calendar.getInstance(),
endDate = Calendar.getInstance())
}
Constructor
named arguments
Lambda
val function: () -> Unit
val function2: (String, Int) -> View
val function3: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function3: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
optional
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
optional
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
optional
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
optional
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction
}
optional
Lambda
val function: () -> Unit
val function: (String, Int) -> View
val function: (String, Int) -> View = {name: String, count: Int -> doAction() }
val button: Button
button.setOnClickListener({ view: View -> doAction() })
button.setOnClickListener({ view -> doAction() })
button.setOnClickListener({ doAction() })
button.setOnClickListener {
doAction()
}
optional
Lambda
Retrolambda
Java8
Lambda
fun test() {
println("one")
println("two")
println("three")
}
Lambda
fun test() {
performAction {
println("two")
}
}
fun performAction(action: () -> Unit) {
println("one")
action()
println("three")
}
fun test() {
println("one")
println("two")
println("three")
}
Lambda
fun test() {
performAction {
println("two")
}
}
fun performAction(action: () -> Unit) {
println("one")
action()
println("three")
}
public final class LabmdaSample {
public final void test() {
this.performAction((Function0)test.INSTANCE);
}
}
Lambda
fun test() {
performAction {
println("two")
}
}
public final class LabmdaSample {
public final void test() {
this.performAction((Function0)test.INSTANCE);
}
}
public final void performAction(@NotNull Function0<Unit> action) {
Intrinsics.checkParameterIsNotNull(action, (String)"action");
String message$iv = "one";
System.out.println((Object)message$iv);
action.invoke();
message$iv = "three";
System.out.println((Object)message$iv);
}
fun performAction(action: () -> Unit) {
println("one")
action()
println("three")
}
Lambda
fun test() {
performAction {
println("two")
}
}
public final class LabmdaSample {
public final void test() {
this.performAction((Function0)test.INSTANCE);
}
}
public final void performAction(@NotNull Function0<Unit> action) {
Intrinsics.checkParameterIsNotNull(action, (String)"action");
String message$iv = "one";
System.out.println((Object)message$iv);
action.invoke();
message$iv = "three";
System.out.println((Object)message$iv);
}
fun performAction(action: () -> Unit) {
println("one")
action()
println("three")
}
Lambda
public final class LabmdaSample {
public final void test() {
this.performAction((Function0)test.INSTANCE);
}
}
public final void performAction(@NotNull Function0<Unit> action) {
Intrinsics.checkParameterIsNotNull(action, (String)"action");
String message$iv = "one";
System.out.println((Object)message$iv);
action.invoke();
message$iv = "three";
System.out.println((Object)message$iv);
}
static final class LabmdaSample.test
extends Lambda
implements Function0<Unit> {
public static final LabmdaSample.test
INSTANCE = new test();
public final void invoke() {
String message$iv = "two";
System.out.println((Object)message$iv);
}
LabmdaSample.test() {
super(0);
}
}
Lambda
fun test() {
performAction {
println("two")
}
}
inline fun performAction(
noinline action: () -> Unit) {
println("one")
action()
println("three")
}
public final void test() {
LabmdaSample labmdaSample = this;
Function0 action$iv = test.INSTANCE;
String message$iv$iv = "one";
System.out.println((Object)message$iv$iv);
action$iv.invoke();
message$iv$iv = "three";
System.out.println((Object)message$iv$iv);
}
Lambda
fun test() {
performAction {
println("two")
}
}
inline fun performAction(
noinline action: () -> Unit) {
println("one")
action()
println("three")
}
disappeared
Lambda
fun test() {
performAction {
println("two")
}
}
inline fun performAction(
action: () -> Unit) {
println("one")
action()
println("three")
}
Let the magic begin
public final void test() {
LabmdaSample this_$iv = this;
String message$iv$iv = "one";
System.out.println((Object)message$iv$iv);
String message$iv = "two";
System.out.println((Object)message$iv);
message$iv$iv = "three";
System.out.println((Object)message$iv$iv);
}
Lambda
fun test() {
performAction {
println("two")
}
}
inline fun performAction(
action: () -> Unit) {
println("one")
action()
println("three")
}
disappeared
class Person(val name: String, val age: Int)
fun Person.isUnderAge()
= age < 18
Extension functions
class Person(val name: String, val age: Int)
fun Person.isUnderAge()
= age < 18
fun test() {
val person = Person("Pawel", 18)
person.isUnderAge()
}
Extension functions
Mixins are a language concept that allows
a programmer to inject some code into a class
class Person(val name: String, val age: Int)
fun Person.isUnderAge()
= age < 18
fun test() {
val person = Person("Pawel", 18)
person.isUnderAge()
}
Extension functions
but, it isn’t mixin
Mixins are a language concept that allows
a programmer to inject some code into a class
public final class Person {
@NotNull
private final String name;
private final int age;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public Person(@NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull((Object)name,
(String)"name");
this.name = name;
this.age = age;
}
}
Extension functions
public final class TestExtensionKt {
public static final boolean isUnderAge(
Person $receiver){
Intrinsics.checkParameterIsNotNull((Object)$receiver,
(String)"$receiver");
return $receiver.getAge() < 18;
}
public static final void test() {
Person person = new Person("Pawel", 18);
}
}
Just like Utils
Patterns and
constructions
52
Extensions != utils
53
fun readFromCursor(cursor: Cursor, name: String): String? {
val columnIndex = cursor.getColumnIndex(name)
return if (cursor.isNull(columnIndex)) {
null
} else {
cursor.getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(readFromCursor(cursor, "name"))
showAge(readFromCursor(cursor, "age"))
} finally {
cursor.close()
}
}
Extensions != utils
id name age
0 Pawel 30
1 Kasia 25
... ... ...
fun readFromCursor(cursor: Cursor, name: String): String? {
val columnIndex = cursor.getColumnIndex(name)
return if (cursor.isNull(columnIndex)) {
null
} else {
cursor.getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(readFromCursor(cursor, "name"))
showAge(readFromCursor(cursor, "age"))
} finally {
cursor.close()
}
}
Extensions != utils
id name age
0 Pawel 30
1 Kasia 25
... ... ... android
fun readFromCursor(cursor: Cursor, name: String): String? {
val columnIndex = cursor.getColumnIndex(name)
return if (cursor.isNull(columnIndex)) {
null
} else {
cursor.getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(readFromCursor(cursor, "name"))
showAge(readFromCursor(cursor, "age"))
} finally {
cursor.close()
}
}
Extensions != utils
id name age
0 Pawel 30
1 Kasia 25
... ... ...
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(readFromCursor(cursor, "name"))
showAge(readFromCursor(cursor, "age"))
} finally {
cursor.close()
}
}
id name age
0 Pawel 30
1 Kasia 25
... ... ...
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(cursor.readString("name"))
showAge(cursor.readString("age"))
} finally {
cursor.close()
}
}
id name age
0 Pawel 30
1 Kasia 25
... ... ...
fun Cursor.closeAfter(action: () -> Unit) {
try {
action()
} finally {
close()
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
try {
showName(cursor.readString("name"))
showAge(cursor.readString("age"))
} finally {
cursor.close()
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(cursor.readString("name"))
showAge(cursor.readString("age"))
}
}
fun Cursor.closeAfter(action: () -> Unit) {
try {
action()
} finally {
close()
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(cursor.readString("name"))
showAge(cursor.readString("age"))
}
}
fun Cursor.closeAfter(action: (Cursor) -> Unit) {
try {
action(this)
} finally {
close()
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(it.readString("name"))
showName(it.readString("age"))
}
}
fun Cursor.closeAfter(action: (Cursor) -> Unit) {
try {
action(this)
} finally {
close()
}
}
it: Cursor
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(it.readString("name"))
showName(it.readString("age"))
}
}
fun Cursor.closeAfter(action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(readString("name"))
showName(readString("age"))
}
}
fun Cursor.closeAfter(action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
} this === cursor
(this as Cursor).action()
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
public static final void show(@NotNull Cursor cursor) {
Intrinsics.checkParameterIsNotNull((Object)cursor,(String)"cursor");
CursorReadyKt.closeAfter(cursor,
(Function1)show.INSTANCE);
}
fun Cursor.closeAfter(action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
}
Extensions != utils
public static final void closeAfter(
Cursor $receiver,
@NotNull Function1<? super Cursor, Unit> action) {
Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver");
Intrinsics.checkParameterIsNotNull(action,(String)"action");
try {
action.invoke((Object)$receiver);
} finally {
$receiver.close();
}
}
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
public static final void show(@NotNull Cursor cursor) {
Intrinsics.checkParameterIsNotNull((Object)cursor,(String)"cursor");
CursorReadyKt.closeAfter(cursor,
(Function1)show.INSTANCE);
}
Extensions != utils
static final class CursorReadyKt.show
extends Lambda
implements Function1<Cursor, Unit> {
public static final CursorReadyKt.show INSTANCE = new ;
public final void invoke(Cursor $receiver) {
Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver");
CursorSampleKt.showName((String)CursorSampleKt.readString(
(Cursor)$receiver,
(String)"name")
);
CursorSampleKt.showName((String)CursorSampleKt.readString(
(Cursor)$receiver,
(String)"age")
);
}
}
public static final void closeAfter(
Cursor $receiver,
@NotNull Function1<? super Cursor, Unit> action) {
Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver");
Intrinsics.checkParameterIsNotNull(action,(String)"action");
try {
action.invoke((Object)$receiver);
} finally {
$receiver.close();
}
}
Extensions != utils
fun Cursor.readString(name: String): String? {
val columnIndex = getColumnIndex(name)
return if (isNull(columnIndex)) {
null
} else {
getString(columnIndex)
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(readString("name"))
showName(readString("age"))
}
}
inline fun Cursor.closeAfter(
action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
}
this === cursor
(this as Cursor).action()
Extensions != utils
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(readString("name"))
showName(readString("age"))
}
}
inline fun Cursor.closeAfter(
action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
}
Extensions != utils
public static final void show(@NotNull Cursor cursor) {
Intrinsics.checkParameterIsNotNull(cursor, "cursor");
try {
Cursor $receiver = cursor;
CursorSampleKt.showName(
CursorSampleKt.readString($receiver, "name"));
CursorSampleKt.showName(
CursorSampleKt.readString($receiver, "age"));
Unit unit = Unit.INSTANCE;
} finally {
cursor.close();
}
}
}
fun show(cursor: Cursor) {
cursor.closeAfter {
showName(readString("name"))
showName(readString("age"))
}
}
inline fun Cursor.closeAfter(
action: Cursor.() -> Unit) {
try {
action()
} finally {
close()
}
}
disappeared
Delegated properties
71
class Example {
var p: String by Delegate()
}
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "example"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
}
}
Delegated properties
Controls access to the field
class SampleActivity : AppCompatActivity {
lateinit val inputMethodManager: InputMethodManager
override fun onCreate(savedInstanceState: Bundle?) {
inputManager: InputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE)
as InputMethodManager
}
}
class SampleActivity : AppCompatActivity {
val inputManager: InputMethodManager
by bindSystemService(Activity.INPUT_METHOD_SERVICE)
override fun onCreate(savedInstanceState: Bundle?) {
}
}
Delegated properties
class SampleActivity : AppCompatActivity {
lateinit val inputMethodManager: InputMethodManager
override fun onCreate(savedInstanceState: Bundle?) {
inputManager: InputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE)
as InputMethodManager
}
}
class SampleActivity : AppCompatActivity {
val inputManager: InputMethodManager
by bindSystemService(Activity.INPUT_METHOD_SERVICE)
override fun onCreate(savedInstanceState: Bundle?) {
}
}
Delegated properties
public interface ReadOnlyProperty<in R, out T> {
public operator fun getValue(thisRef: R, property: KProperty<*>): T
}
class Lazy<T, V>(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty<T, V> {
private object EMPTY
private var value: Any? = EMPTY
override fun getValue(thisRef: T, property: KProperty<*>): V {
if (value == EMPTY) {
value = initializer(thisRef, property)
}
@Suppress("UNCHECKED_CAST")
return value as V
}
}
Delegated properties
Helps to remember about syntax
Calls given factory lazy
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = Lazy { activity: Activity, property: KProperty<*> ->
activity.getSystemServicce(serviceName) as V?
?: systemServiceNotFound(serviceName, property)
}
Delegated properties
Helper interface Lazy factory caller
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = Lazy { activity: Activity, property: KProperty<*> ->
activity.getSystemServicce(serviceName) as V?
?: systemServiceNotFound(serviceName, property)
}
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService)
@Suppress("UNCHECKED_CAST")
inline fun <V> fetchSystemService(serviceName: String,
crossinline serviceBinder: Activity.(String) -> Any)
= Lazy { t: Activity, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
Delegated properties
Helper interface Lazy factory caller
Extract service !!
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService)
@Suppress("UNCHECKED_CAST")
inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any)
= Lazy { t: Activity, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
Delegated properties
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService)
fun <V> Fragment.bindSystemService(serviceName: String)
: ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder)
@Suppress("UNCHECKED_CAST")
inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any)
= Lazy { t: Activity, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
Delegated properties
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService)
fun <V> Fragment.bindSystemService(serviceName: String)
: ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder)
@Suppress("UNCHECKED_CAST")
inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any)
= Lazy { t: Activity, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
@Suppress("UNCHECKED_CAST")
inline fun <T, V> fetchSystemService(serviceName: String, crossinline serviceBinder: T.(String) -> Any)
= Lazy { t: T, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
Delegated properties
fun <V> Activity.bindSystemService(serviceName: String)
: ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService)
fun <V> Fragment.bindSystemService(serviceName: String)
: ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder)
@Suppress("UNCHECKED_CAST")
inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any)
= Lazy { t: Activity, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
@Suppress("UNCHECKED_CAST")
inline fun <T, V> fetchSystemService(serviceName: String, crossinline serviceBinder: T.(String) -> Any)
= Lazy { t: T, property: KProperty<*> ->
t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property)
}
Delegated properties
Facts
82
Size
Methods Dex size (KB)
kotlin-stdlib 6961 1085
kotlin-runtime 924 149
7885 1234
Compilation
BUILD SUCCESSFUL
Total time: 1 mins 45.011 secs
== Build Time Summary ==
:app:clean (0:00.667) ▇ 1%
:app:prepareAndroidBrasterLibraryUnspecifiedLibrary (0:00.926) ▇▇ 1%
:app:prepareComAndroidSupportAppcompatV72330Library (0:00.345) 0%
:app:prepareIoRealmRealmAndroidLibrary100Library (0:00.151) 0%
:app:mergeDebugAssets (0:00.058) 0%
:app:processDebugManifest (0:00.200) 0%
:app:fabricGenerateResourcesDebug (0:00.119) 0%
:app:mergeDebugResources (0:09.250) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 9%
:app:dataBindingProcessLayoutsDebug (0:00.695) ▇ 1%
:app:generateDebugSettings (0:00.139) 0%
:app:processDebugResources (0:00.668) ▇ 1%
:app:compileDebugKotlin (0:13.807) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 14%
:app:compileDebugJavaWithJavac (0:04.937) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 5%
:app:compileDebugGroovyWithGroovyc (0:03.566) ▇▇▇▇▇▇▇▇▇▇ 4%
:app:compileDebugKotlinAfterJava (0:11.675) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 12%
:app:transformClassesWithRealmTransformerForDebug (0:01.685) ▇▇▇▇ 2%
:app:transformClassesWithDexForDebug (0:37.963)<-- ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 39%
:app:transformNative_libsWithMergeJniLibsForDebug (0:00.516) ▇ 1%
:app:transformResourcesWithMergeJavaResForDebug (0:00.204) 0%
:app:packageDebug (0:09.790) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 10%
:app:zipalignDebug (0:00.315) 0%
== BUILD SUCCESSFUL ==
Compilation
BUILD SUCCESSFUL
Total time: 1 mins 45.011 secs
== Build Time Summary ==
:app:clean (0:00.667) ▇ 1%
:app:prepareAndroidBrasterLibraryUnspecifiedLibrary (0:00.926) ▇▇ 1%
:app:prepareComAndroidSupportAppcompatV72330Library (0:00.345) 0%
:app:prepareIoRealmRealmAndroidLibrary100Library (0:00.151) 0%
:app:mergeDebugAssets (0:00.058) 0%
:app:processDebugManifest (0:00.200) 0%
:app:fabricGenerateResourcesDebug (0:00.119) 0%
:app:mergeDebugResources (0:09.250) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 9%
:app:dataBindingProcessLayoutsDebug (0:00.695) ▇ 1%
:app:generateDebugSettings (0:00.139) 0%
:app:processDebugResources (0:00.668) ▇ 1%
:app:compileDebugKotlin (0:13.807) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 14%
:app:compileDebugJavaWithJavac (0:04.937) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 5%
:app:compileDebugGroovyWithGroovyc (0:03.566) ▇▇▇▇▇▇▇▇▇▇ 4%
:app:compileDebugKotlinAfterJava (0:11.675) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 12%
:app:transformClassesWithRealmTransformerForDebug (0:01.685) ▇▇▇▇ 2%
:app:transformClassesWithDexForDebug (0:37.963)<-- ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 39%
:app:transformNative_libsWithMergeJniLibsForDebug (0:00.516) ▇ 1%
:app:transformResourcesWithMergeJavaResForDebug (0:00.204) 0%
:app:packageDebug (0:09.790) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 10%
:app:zipalignDebug (0:00.315) 0%
== BUILD SUCCESSFUL ==
26%
What next?
Kotlin 1.0.x which will be a series of releases containing bug fixes, updates to tooling, IDE support and other areas which do not affect the core language.
1.0.x releases will be published on a regular basis once every several weeks.
Kotlin 1.1 which will contain major new language features, along with all the improvements from the 1.0.x branch. This will be a feature-driven
release, and we aren’t announcing any specific time frame for it.
async/await/yield
Type aliases
Local delegated properties
Java 8/9 Support
Jack and Jill toolchain
Instant Run
Summary
Syntax
Inline
Java
88
Pawel Byszewski
pawel.byszewski@polidea.com
pawell.b@gmail.com
https://twitter.com/PawelByszewski
89
Pawel Byszewski
THANK
YOU
http://www.meetup.com/Mobile-Warsaw/
FGST
Free GoogleSlides
Templates

Kotlin, why?

  • 1.
  • 2.
    What is thetalk about? Only necessary Syntax Code patterns Facts and analysis
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    class Conference(var name:String, val startDate: Calendar, val endDate: Calendar) class Conference2(name: String, val startDate: Calendar, val endDate: Calendar) { var name: String = name get() = "prefix_$field" set(value) { field = "${value}_sufix" } } Getters and setters
  • 12.
    class Conference(var name:String, val startDate: Calendar, val endDate: Calendar) class Conference2(name: String, val startDate: Calendar, val endDate: Calendar) { var name: String = name get() = "prefix_$field" set(value) { field = "${value}_sufix" } } Getters and setters val - finalvar - not final
  • 13.
    class Conference(name: String, valstartDate: Calendar, val endDate: Calendar) { var name: String = name } Getters and setters val - finalvar - not final
  • 14.
    class Conference(name: String, valstartDate: Calendar, val endDate: Calendar) { var name: String = name get() = "prefix_$field" } Getters and setters “prefix” + field val - finalvar - not final
  • 15.
    class Conference(name: String, valstartDate: Calendar, val endDate: Calendar) { var name: String = name get() = "prefix_$field" } Getters and setters “prefix” + field val - finalvar - not final field - backing field for property
  • 16.
    class Conference(name: String, valstartDate: Calendar, val endDate: Calendar) { var name: String = name get() = "prefix_$field" set(value) { field = "${value}_sufix" } } Getters and setters “prefix” + field val - finalvar - not final field - backing field for property
  • 17.
  • 18.
    Getters and setters classConference(val name: String, val startDate: Calendar, val endDate: Calendar) { val passed: Boolean get() = Calendar.getInstance().after(endDate) } It is property like in C#, not java field
  • 19.
    Getters and setters classConference(val name: String, val startDate: Calendar, val endDate: Calendar) { val passed: Boolean get() = Calendar.getInstance().after(endDate) } It doesn’t exist It is property like in C#, not java field
  • 20.
    Constructor class Conference(val name:String, val city: String) fun test() { val conference = Conference("Confitura", "Warsaw") }
  • 21.
  • 22.
    Constructor class Conference(val name:String, val city: String, val isFree: Boolean) fun test() { val conference = Conference("Confitura", "Warsaw") }
  • 23.
    Constructor class Conference(val name:String, val city: String, val isFree: Boolean = false) fun test() { val conference = Conference("Confitura", "Warsaw") }
  • 24.
    public Conference(@NotNull Stringname, @NotNull String city, boolean isFree) { Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(city, "city"); this.name = name; this.city = city; this.isFree = isFree; } Constructor One to rulethem all
  • 25.
    public Conference(@NotNull Stringname, @NotNull String city, boolean isFree) { Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(city, "city"); this.name = name; this.city = city; this.isFree = isFree; } Constructor val conference = Conference("Confitura", "Warsaw") One to rulethem all
  • 26.
    public Conference(@NotNull Stringname, @NotNull String city, boolean isFree) { Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(city, "city"); this.name = name; this.city = city; this.isFree = isFree; } Constructor public static final void test() { Conference conference = new Conference("Confitura", "Warsaw", false); } val conference = Conference("Confitura", "Warsaw") One to rulethem all
  • 27.
    class Conference(val name:String, val startDate: Calendar, val endDate: Calendar) fun test() { val conference1 = Conference("Confitura", Calendar.getInstance(), Calendar.getInstance()) val conference2 = Conference(name = "Confitura", startDate = Calendar.getInstance(), endDate = Calendar.getInstance()) } Constructor
  • 28.
    class Conference(val name:String, val startDate: Calendar, val endDate: Calendar) fun test() { val conference1 = Conference("Confitura", Calendar.getInstance(), Calendar.getInstance()) val conference2 = Conference(name = "Confitura", startDate = Calendar.getInstance(), endDate = Calendar.getInstance()) } Constructor named arguments
  • 29.
    Lambda val function: ()-> Unit val function2: (String, Int) -> View val function3: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction }
  • 30.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function3: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction }
  • 31.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction } optional
  • 32.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction } optional
  • 33.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction } optional
  • 34.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction } optional
  • 35.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction } optional
  • 36.
    Lambda val function: ()-> Unit val function: (String, Int) -> View val function: (String, Int) -> View = {name: String, count: Int -> doAction() } val button: Button button.setOnClickListener({ view: View -> doAction() }) button.setOnClickListener({ view -> doAction() }) button.setOnClickListener({ doAction() }) button.setOnClickListener { doAction() } optional
  • 37.
  • 38.
  • 39.
    Lambda fun test() { performAction{ println("two") } } fun performAction(action: () -> Unit) { println("one") action() println("three") } fun test() { println("one") println("two") println("three") }
  • 40.
    Lambda fun test() { performAction{ println("two") } } fun performAction(action: () -> Unit) { println("one") action() println("three") } public final class LabmdaSample { public final void test() { this.performAction((Function0)test.INSTANCE); } }
  • 41.
    Lambda fun test() { performAction{ println("two") } } public final class LabmdaSample { public final void test() { this.performAction((Function0)test.INSTANCE); } } public final void performAction(@NotNull Function0<Unit> action) { Intrinsics.checkParameterIsNotNull(action, (String)"action"); String message$iv = "one"; System.out.println((Object)message$iv); action.invoke(); message$iv = "three"; System.out.println((Object)message$iv); } fun performAction(action: () -> Unit) { println("one") action() println("three") }
  • 42.
    Lambda fun test() { performAction{ println("two") } } public final class LabmdaSample { public final void test() { this.performAction((Function0)test.INSTANCE); } } public final void performAction(@NotNull Function0<Unit> action) { Intrinsics.checkParameterIsNotNull(action, (String)"action"); String message$iv = "one"; System.out.println((Object)message$iv); action.invoke(); message$iv = "three"; System.out.println((Object)message$iv); } fun performAction(action: () -> Unit) { println("one") action() println("three") }
  • 43.
    Lambda public final classLabmdaSample { public final void test() { this.performAction((Function0)test.INSTANCE); } } public final void performAction(@NotNull Function0<Unit> action) { Intrinsics.checkParameterIsNotNull(action, (String)"action"); String message$iv = "one"; System.out.println((Object)message$iv); action.invoke(); message$iv = "three"; System.out.println((Object)message$iv); } static final class LabmdaSample.test extends Lambda implements Function0<Unit> { public static final LabmdaSample.test INSTANCE = new test(); public final void invoke() { String message$iv = "two"; System.out.println((Object)message$iv); } LabmdaSample.test() { super(0); } }
  • 44.
    Lambda fun test() { performAction{ println("two") } } inline fun performAction( noinline action: () -> Unit) { println("one") action() println("three") }
  • 45.
    public final voidtest() { LabmdaSample labmdaSample = this; Function0 action$iv = test.INSTANCE; String message$iv$iv = "one"; System.out.println((Object)message$iv$iv); action$iv.invoke(); message$iv$iv = "three"; System.out.println((Object)message$iv$iv); } Lambda fun test() { performAction { println("two") } } inline fun performAction( noinline action: () -> Unit) { println("one") action() println("three") } disappeared
  • 46.
    Lambda fun test() { performAction{ println("two") } } inline fun performAction( action: () -> Unit) { println("one") action() println("three") } Let the magic begin
  • 47.
    public final voidtest() { LabmdaSample this_$iv = this; String message$iv$iv = "one"; System.out.println((Object)message$iv$iv); String message$iv = "two"; System.out.println((Object)message$iv); message$iv$iv = "three"; System.out.println((Object)message$iv$iv); } Lambda fun test() { performAction { println("two") } } inline fun performAction( action: () -> Unit) { println("one") action() println("three") } disappeared
  • 48.
    class Person(val name:String, val age: Int) fun Person.isUnderAge() = age < 18 Extension functions
  • 49.
    class Person(val name:String, val age: Int) fun Person.isUnderAge() = age < 18 fun test() { val person = Person("Pawel", 18) person.isUnderAge() } Extension functions Mixins are a language concept that allows a programmer to inject some code into a class
  • 50.
    class Person(val name:String, val age: Int) fun Person.isUnderAge() = age < 18 fun test() { val person = Person("Pawel", 18) person.isUnderAge() } Extension functions but, it isn’t mixin Mixins are a language concept that allows a programmer to inject some code into a class
  • 51.
    public final classPerson { @NotNull private final String name; private final int age; @NotNull public final String getName() { return this.name; } public final int getAge() { return this.age; } public Person(@NotNull String name, int age) { Intrinsics.checkParameterIsNotNull((Object)name, (String)"name"); this.name = name; this.age = age; } } Extension functions public final class TestExtensionKt { public static final boolean isUnderAge( Person $receiver){ Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver"); return $receiver.getAge() < 18; } public static final void test() { Person person = new Person("Pawel", 18); } } Just like Utils
  • 52.
  • 53.
  • 54.
    fun readFromCursor(cursor: Cursor,name: String): String? { val columnIndex = cursor.getColumnIndex(name) return if (cursor.isNull(columnIndex)) { null } else { cursor.getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(readFromCursor(cursor, "name")) showAge(readFromCursor(cursor, "age")) } finally { cursor.close() } } Extensions != utils id name age 0 Pawel 30 1 Kasia 25 ... ... ...
  • 55.
    fun readFromCursor(cursor: Cursor,name: String): String? { val columnIndex = cursor.getColumnIndex(name) return if (cursor.isNull(columnIndex)) { null } else { cursor.getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(readFromCursor(cursor, "name")) showAge(readFromCursor(cursor, "age")) } finally { cursor.close() } } Extensions != utils id name age 0 Pawel 30 1 Kasia 25 ... ... ... android
  • 56.
    fun readFromCursor(cursor: Cursor,name: String): String? { val columnIndex = cursor.getColumnIndex(name) return if (cursor.isNull(columnIndex)) { null } else { cursor.getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(readFromCursor(cursor, "name")) showAge(readFromCursor(cursor, "age")) } finally { cursor.close() } } Extensions != utils id name age 0 Pawel 30 1 Kasia 25 ... ... ...
  • 57.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(readFromCursor(cursor, "name")) showAge(readFromCursor(cursor, "age")) } finally { cursor.close() } } id name age 0 Pawel 30 1 Kasia 25 ... ... ...
  • 58.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(cursor.readString("name")) showAge(cursor.readString("age")) } finally { cursor.close() } } id name age 0 Pawel 30 1 Kasia 25 ... ... ...
  • 59.
    fun Cursor.closeAfter(action: ()-> Unit) { try { action() } finally { close() } } Extensions != utils fun Cursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { try { showName(cursor.readString("name")) showAge(cursor.readString("age")) } finally { cursor.close() } }
  • 60.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(cursor.readString("name")) showAge(cursor.readString("age")) } } fun Cursor.closeAfter(action: () -> Unit) { try { action() } finally { close() } }
  • 61.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(cursor.readString("name")) showAge(cursor.readString("age")) } } fun Cursor.closeAfter(action: (Cursor) -> Unit) { try { action(this) } finally { close() } }
  • 62.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(it.readString("name")) showName(it.readString("age")) } } fun Cursor.closeAfter(action: (Cursor) -> Unit) { try { action(this) } finally { close() } } it: Cursor
  • 63.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(it.readString("name")) showName(it.readString("age")) } } fun Cursor.closeAfter(action: Cursor.() -> Unit) { try { action() } finally { close() } }
  • 64.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(readString("name")) showName(readString("age")) } } fun Cursor.closeAfter(action: Cursor.() -> Unit) { try { action() } finally { close() } } this === cursor (this as Cursor).action()
  • 65.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } public static final void show(@NotNull Cursor cursor) { Intrinsics.checkParameterIsNotNull((Object)cursor,(String)"cursor"); CursorReadyKt.closeAfter(cursor, (Function1)show.INSTANCE); } fun Cursor.closeAfter(action: Cursor.() -> Unit) { try { action() } finally { close() } }
  • 66.
    Extensions != utils publicstatic final void closeAfter( Cursor $receiver, @NotNull Function1<? super Cursor, Unit> action) { Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver"); Intrinsics.checkParameterIsNotNull(action,(String)"action"); try { action.invoke((Object)$receiver); } finally { $receiver.close(); } } fun Cursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } public static final void show(@NotNull Cursor cursor) { Intrinsics.checkParameterIsNotNull((Object)cursor,(String)"cursor"); CursorReadyKt.closeAfter(cursor, (Function1)show.INSTANCE); }
  • 67.
    Extensions != utils staticfinal class CursorReadyKt.show extends Lambda implements Function1<Cursor, Unit> { public static final CursorReadyKt.show INSTANCE = new ; public final void invoke(Cursor $receiver) { Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver"); CursorSampleKt.showName((String)CursorSampleKt.readString( (Cursor)$receiver, (String)"name") ); CursorSampleKt.showName((String)CursorSampleKt.readString( (Cursor)$receiver, (String)"age") ); } } public static final void closeAfter( Cursor $receiver, @NotNull Function1<? super Cursor, Unit> action) { Intrinsics.checkParameterIsNotNull((Object)$receiver, (String)"$receiver"); Intrinsics.checkParameterIsNotNull(action,(String)"action"); try { action.invoke((Object)$receiver); } finally { $receiver.close(); } }
  • 68.
    Extensions != utils funCursor.readString(name: String): String? { val columnIndex = getColumnIndex(name) return if (isNull(columnIndex)) { null } else { getString(columnIndex) } } fun show(cursor: Cursor) { cursor.closeAfter { showName(readString("name")) showName(readString("age")) } } inline fun Cursor.closeAfter( action: Cursor.() -> Unit) { try { action() } finally { close() } } this === cursor (this as Cursor).action()
  • 69.
    Extensions != utils funshow(cursor: Cursor) { cursor.closeAfter { showName(readString("name")) showName(readString("age")) } } inline fun Cursor.closeAfter( action: Cursor.() -> Unit) { try { action() } finally { close() } }
  • 70.
    Extensions != utils publicstatic final void show(@NotNull Cursor cursor) { Intrinsics.checkParameterIsNotNull(cursor, "cursor"); try { Cursor $receiver = cursor; CursorSampleKt.showName( CursorSampleKt.readString($receiver, "name")); CursorSampleKt.showName( CursorSampleKt.readString($receiver, "age")); Unit unit = Unit.INSTANCE; } finally { cursor.close(); } } } fun show(cursor: Cursor) { cursor.closeAfter { showName(readString("name")) showName(readString("age")) } } inline fun Cursor.closeAfter( action: Cursor.() -> Unit) { try { action() } finally { close() } } disappeared
  • 71.
  • 72.
    class Example { varp: String by Delegate() } class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "example" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { } } Delegated properties Controls access to the field
  • 73.
    class SampleActivity :AppCompatActivity { lateinit val inputMethodManager: InputMethodManager override fun onCreate(savedInstanceState: Bundle?) { inputManager: InputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager } } class SampleActivity : AppCompatActivity { val inputManager: InputMethodManager by bindSystemService(Activity.INPUT_METHOD_SERVICE) override fun onCreate(savedInstanceState: Bundle?) { } } Delegated properties
  • 74.
    class SampleActivity :AppCompatActivity { lateinit val inputMethodManager: InputMethodManager override fun onCreate(savedInstanceState: Bundle?) { inputManager: InputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager } } class SampleActivity : AppCompatActivity { val inputManager: InputMethodManager by bindSystemService(Activity.INPUT_METHOD_SERVICE) override fun onCreate(savedInstanceState: Bundle?) { } } Delegated properties
  • 75.
    public interface ReadOnlyProperty<inR, out T> { public operator fun getValue(thisRef: R, property: KProperty<*>): T } class Lazy<T, V>(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty<T, V> { private object EMPTY private var value: Any? = EMPTY override fun getValue(thisRef: T, property: KProperty<*>): V { if (value == EMPTY) { value = initializer(thisRef, property) } @Suppress("UNCHECKED_CAST") return value as V } } Delegated properties Helps to remember about syntax Calls given factory lazy
  • 76.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = Lazy { activity: Activity, property: KProperty<*> -> activity.getSystemServicce(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties Helper interface Lazy factory caller
  • 77.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = Lazy { activity: Activity, property: KProperty<*> -> activity.getSystemServicce(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } fun <V> Activity.bindSystemService(serviceName: String) : ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService) @Suppress("UNCHECKED_CAST") inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any) = Lazy { t: Activity, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties Helper interface Lazy factory caller Extract service !!
  • 78.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService) @Suppress("UNCHECKED_CAST") inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any) = Lazy { t: Activity, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties
  • 79.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService) fun <V> Fragment.bindSystemService(serviceName: String) : ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder) @Suppress("UNCHECKED_CAST") inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any) = Lazy { t: Activity, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties
  • 80.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService) fun <V> Fragment.bindSystemService(serviceName: String) : ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder) @Suppress("UNCHECKED_CAST") inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any) = Lazy { t: Activity, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } @Suppress("UNCHECKED_CAST") inline fun <T, V> fetchSystemService(serviceName: String, crossinline serviceBinder: T.(String) -> Any) = Lazy { t: T, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties
  • 81.
    fun <V> Activity.bindSystemService(serviceName:String) : ReadOnlyProperty<Activity, V> = fetchSystemService(serviceName, Activity::getSystemService) fun <V> Fragment.bindSystemService(serviceName: String) : ReadOnlyProperty<Fragment, V> = fetchSystemService(serviceName, Fragment::serviceBinder) @Suppress("UNCHECKED_CAST") inline fun <V> fetchSystemService(serviceName: String, crossinline serviceBinder: Activity.(String) -> Any) = Lazy { t: Activity, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } @Suppress("UNCHECKED_CAST") inline fun <T, V> fetchSystemService(serviceName: String, crossinline serviceBinder: T.(String) -> Any) = Lazy { t: T, property: KProperty<*> -> t.serviceBinder(serviceName) as V? ?: systemServiceNotFound(serviceName, property) } Delegated properties
  • 82.
  • 83.
    Size Methods Dex size(KB) kotlin-stdlib 6961 1085 kotlin-runtime 924 149 7885 1234
  • 84.
    Compilation BUILD SUCCESSFUL Total time:1 mins 45.011 secs == Build Time Summary == :app:clean (0:00.667) ▇ 1% :app:prepareAndroidBrasterLibraryUnspecifiedLibrary (0:00.926) ▇▇ 1% :app:prepareComAndroidSupportAppcompatV72330Library (0:00.345) 0% :app:prepareIoRealmRealmAndroidLibrary100Library (0:00.151) 0% :app:mergeDebugAssets (0:00.058) 0% :app:processDebugManifest (0:00.200) 0% :app:fabricGenerateResourcesDebug (0:00.119) 0% :app:mergeDebugResources (0:09.250) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 9% :app:dataBindingProcessLayoutsDebug (0:00.695) ▇ 1% :app:generateDebugSettings (0:00.139) 0% :app:processDebugResources (0:00.668) ▇ 1% :app:compileDebugKotlin (0:13.807) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 14% :app:compileDebugJavaWithJavac (0:04.937) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 5% :app:compileDebugGroovyWithGroovyc (0:03.566) ▇▇▇▇▇▇▇▇▇▇ 4% :app:compileDebugKotlinAfterJava (0:11.675) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 12% :app:transformClassesWithRealmTransformerForDebug (0:01.685) ▇▇▇▇ 2% :app:transformClassesWithDexForDebug (0:37.963)<-- ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 39% :app:transformNative_libsWithMergeJniLibsForDebug (0:00.516) ▇ 1% :app:transformResourcesWithMergeJavaResForDebug (0:00.204) 0% :app:packageDebug (0:09.790) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 10% :app:zipalignDebug (0:00.315) 0% == BUILD SUCCESSFUL ==
  • 85.
    Compilation BUILD SUCCESSFUL Total time:1 mins 45.011 secs == Build Time Summary == :app:clean (0:00.667) ▇ 1% :app:prepareAndroidBrasterLibraryUnspecifiedLibrary (0:00.926) ▇▇ 1% :app:prepareComAndroidSupportAppcompatV72330Library (0:00.345) 0% :app:prepareIoRealmRealmAndroidLibrary100Library (0:00.151) 0% :app:mergeDebugAssets (0:00.058) 0% :app:processDebugManifest (0:00.200) 0% :app:fabricGenerateResourcesDebug (0:00.119) 0% :app:mergeDebugResources (0:09.250) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 9% :app:dataBindingProcessLayoutsDebug (0:00.695) ▇ 1% :app:generateDebugSettings (0:00.139) 0% :app:processDebugResources (0:00.668) ▇ 1% :app:compileDebugKotlin (0:13.807) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 14% :app:compileDebugJavaWithJavac (0:04.937) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 5% :app:compileDebugGroovyWithGroovyc (0:03.566) ▇▇▇▇▇▇▇▇▇▇ 4% :app:compileDebugKotlinAfterJava (0:11.675) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 12% :app:transformClassesWithRealmTransformerForDebug (0:01.685) ▇▇▇▇ 2% :app:transformClassesWithDexForDebug (0:37.963)<-- ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 39% :app:transformNative_libsWithMergeJniLibsForDebug (0:00.516) ▇ 1% :app:transformResourcesWithMergeJavaResForDebug (0:00.204) 0% :app:packageDebug (0:09.790) ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 10% :app:zipalignDebug (0:00.315) 0% == BUILD SUCCESSFUL == 26%
  • 86.
    What next? Kotlin 1.0.xwhich will be a series of releases containing bug fixes, updates to tooling, IDE support and other areas which do not affect the core language. 1.0.x releases will be published on a regular basis once every several weeks. Kotlin 1.1 which will contain major new language features, along with all the improvements from the 1.0.x branch. This will be a feature-driven release, and we aren’t announcing any specific time frame for it. async/await/yield Type aliases Local delegated properties Java 8/9 Support Jack and Jill toolchain Instant Run
  • 87.
  • 88.
  • 89.
  • 90.