but i like java! - goto conference · "i call it my billion-dollar mistake... [which] has led...
TRANSCRIPT
![Page 1: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/1.jpg)
@tsmith
![Page 2: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/2.jpg)
@tsmith
![Page 3: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/3.jpg)
But I like Java!• We're stuck in a Java purgatory• Error prone Code (no non-capturing anonymous inner classes)• General Java language restrictions
@tsmith
![Page 4: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/4.jpg)
How about Groovy?• Groovy is dynamic• Harder for IDEs to parse and infer• Won't ever be consistent with Android
@tsmith
![Page 5: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/5.jpg)
What is Kotlin?• Built by Jetbrains and Open Source• Official Gradle support• Java 6 bytecode compatible• Interoperable with Java• Small standard library (625kb)• Statically typed with no runtime overhead• Modern Language@tsmith
![Page 6: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/6.jpg)
How can Kotlin help today?• Reduce common errors• Reduce boilerplate• Improve Android API• Concise and expressive for build scripts
@tsmith
![Page 7: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/7.jpg)
Kotlin FeaturesHigher-order functions, properties, mixins and delegation, extension functions, static nullability checking, automatic casts, reified generics, declaration-site variance, modules and build infrastructure, inline-functions (zero-overhead closures), operator overloading, String interpolation, pattern matching, first class IDE support with Java converter, default parameters, infix methods, and more...
@tsmith
![Page 8: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/8.jpg)
Nullability"I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."— Sir Charles Antony Richard Hoare
@tsmith
![Page 9: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/9.jpg)
Nullabilityvar a: String = "foo" //Reversed Type and namea = null //Compilation error
@tsmith
![Page 10: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/10.jpg)
Nullabilityvar b: String? = "bar"b = null //ok
val l = b.length //Compilation error
@tsmith
![Page 11: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/11.jpg)
Nullabilityval l = b?.length //Value null
//With a default valueval l = if (b != null) b.length else -1 //Value -1
//or with the Elvis operatorval l = b?.length ?: -1 //Value -1
@tsmith
![Page 12: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/12.jpg)
Propertiesclass User(var name: String) {...}
fun setName(name: String): User { val user = User() // there's no 'new' keyword in Kotlin user.name = "Ty" //This is using a method, not a field return user}
@tsmith
![Page 13: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/13.jpg)
Propertiesclass User { var name: String = ... get() = name // Can declare methods inline set(value) { name = value().toLowerCase() }}
@tsmith
![Page 14: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/14.jpg)
Data classdata class User(name: String) {}
• equals() and hashCode()• toString() of the form "User(name=John)",• copy()
@tsmith
![Page 15: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/15.jpg)
Function Literal (Lambda)Undeclared function bodies used as an expression (ie, as data).val sum: (Int, Int) -> Int = {x, y -> x+y }val anAnswer = sum(6,7) //Variable type is inferred
//Or use "it" to get the inferred parameter
val double: (Int) -> Int = {it*2}val theAnswer = double(21)
@tsmith
![Page 16: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/16.jpg)
Higher Order FunctionsA higher-order function is a function that takes functions as parameters, or returns a functionfun apply(one: Int, two: Int, func: (Int, Int) -> Int) = func(one, two)//Kotlin has great generic support to simplify this too!
val multiply = apply(6, 7) {x, y -> x * y}val difference = apply(44, 2) {x, y -> x -y}
@tsmith
![Page 17: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/17.jpg)
Extension FunctionsFunctions added to a type without modifying the original.fun Int.differenceFromTheAnswer(): Int { return 42 - this}
//Or the Single Expression Function versionfun Int.differenceFromTheAnswer(): = 42 - this
//Usageval difference = 2.differenceFromTheAnswer() //40
@tsmith
![Page 18: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/18.jpg)
Extension FunctionsJava Interoperability//Example 1:@file:JvmName("IntUtil")fun Int.differenceFromTheAnswer(): = 42 - this
//Example 2:@file:JvmName("Util")@file:JvmMultifileClassfun Int.differenceFromTheAnswer(): = 42 - this
@tsmith
![Page 19: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/19.jpg)
Extension Functions in AndroidSharedPreferences.Editor editor;editor = getSharedPreferences(MODE_PRIVATE).edit();editor.putString("login_token", token);editor.apply();
@tsmith
![Page 20: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/20.jpg)
Extension Functions in AndroidAlso Higher Order functions and Function Literals!fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit) { val editor = SharedPreferences.Editor() editor.func() editor.apply()}
getSharedPreferences(MODE_PRIVATE).edit { putString("login_token", token)}
@tsmith
![Page 21: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/21.jpg)
Inline Functions//All the memory allocationfun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit)
//inlines into java byte code, matching the java signatureinline fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit)
@tsmith
![Page 22: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/22.jpg)
BuildersAnkoverticalLayout { padding = dip(16) textView("Username:") { textSize = 18f }.layoutParams { verticalMargin = dip(4) }
val login = editText()
button("Sign up") { textSize = 20f onClick { login(login.text) } }.layoutParams { topMargin = dip(8) }}
@tsmith
![Page 23: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/23.jpg)
Kotlin -> Gradle
@tsmith
![Page 24: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/24.jpg)
Installing Kotlinbuildscript { ext.kotlin_version = '1.0.1'
repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }}
apply plugin: 'kotlin'repositories { mavenCentral() }dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"}
@tsmith
![Page 25: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/25.jpg)
build.gradle.ktsbuildscript { repositories { jcenter() gradleScriptKotlin() } dependencies { classpath("com.android.tools.build:gradle:2.2.0") }}
apply<AppPlugin>()
android { buildToolsVersion("23.0.3") compileSdkVersion(23) defaultConfigExtension { setMinSdkVersion(15) setTargetSdkVersion(23) applicationId = "com.example.kotlingradle" versionCode = 1 versionName = "1.0" }}
@tsmith
![Page 26: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/26.jpg)
build.gradle.kts Extension Functions fun Project.android(setup: AppExtension.() -> Unit) = the<AppExtension>().setup()
fun NamedDomainObjectContainer<BuildType>.release(setup: BuildType.() -> Unit) = findByName("release").setup()
fun AppExtension.defaultConfigExtension(setup: DefaultProductFlavor.() -> Unit) = defaultConfig.setup()
fun AppExtension.buildTypesExtension(setup: NamedDomainObjectContainer<BuildType>.() -> Unit) = buildTypes { it.setup() }
fun DefaultProductFlavor.setMinSdkVersion(value: Int) = setMinSdkVersion(value.asApiVersion())
fun DefaultProductFlavor.setTargetSdkVersion(value: Int) = setTargetSdkVersion(value.asApiVersion())
fun Int.asApiVersion(): ApiVersion = DefaultApiVersion.create(this)
@tsmith
![Page 27: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/27.jpg)
The case of API Keyspublic class SampleApplication extends Application { private static final String CONSUMER_KEY = "PRODUCTION_KEY"; private static final String CONSUMER_SECRET = "PRODUCTION_SECRET"; @Override public void onCreate() { super.onCreate(); SessionConfig authConfig = new SessionConfig(CONSUMER_KEY, CONSUMER_SECRET); Sdk.init(authConfig); }}
@tsmith
![Page 28: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/28.jpg)
The case of API Keysprivate static final String CONSUMER_KEY = "PRODUCTION_KEY";private static final String CONSUMER_SECRET = "PRODUCTION_KEY";
...final SessionConfig authConfig = new SessionConfig(CONSUMER_KEY, CONSUMER_SECRET);
@tsmith
![Page 29: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/29.jpg)
Enter Gradleandroid { buildTypes { release { buildConfigField 'String', 'CONSUMER_KEY', "\"PRODUCTION_KEY\"" buildConfigField 'String', 'CONSUMER_SECRET', "\"PRODUCTION_SECRET\"" } debug { buildConfigField 'String', 'CONSUMER_KEY', '\"DEBUG_KEY\"' buildConfigField 'String', 'CONSUMER_SECRET', '\"DEBUG_SECRET\"' } } ...
@tsmith
![Page 30: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/30.jpg)
BuildConfig classpublic final class BuildConfig { public static final String CONSUMER_KEY = "PRODUCTION_KEY"; ...
public class AwesomeApplication extends Application { private static final String CONSUMER_KEY = BuildConfig.CONSUMER_KEY;
@tsmith
![Page 31: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/31.jpg)
Gradle properties• Gradle (Project) Properties• System Variables• Custom properties file
@tsmith
![Page 32: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/32.jpg)
Provided valuesdef getProp(String key) {
if (System.properties.get(key) != null) { return System.properties.get(key) } else if (project.hasProperty(key)) { return project.property(key) }
throw new GradleException("${key} is not available")}
@tsmith
![Page 33: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/33.jpg)
Using the provided value//Using provided value via getProp functionrelease { buildConfigField "String", "CONSUMER_KEY", "${getProp("INJECTED_KEY")}"...
@tsmith
![Page 34: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/34.jpg)
custom.properties
INJECTED_KEY=PRODUCTION_KEYINJECTED_SECRET=PRODUCTION_SECRET...
@tsmith
![Page 35: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/35.jpg)
Custom Tasktask createCustomPropertiesFile << { def props = new Properties() props.put('INJECTED_KEY', getProp('INJECTED_KEY')) props.put('INJECTED_SECRET', getProp('INJECTED_SECRET'))
file('custom.properties').withOutputStream { props.store(it, "") }}
@tsmith
![Page 36: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/36.jpg)
Custom Properties filetasks << 'createCustomPropertiesFile' { ...}
$ ./gradlew createCustomPropertiesFile -PINJECTED_KEY=DEV_KEY
@tsmith
![Page 37: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/37.jpg)
Gradle pluginBasic ingredients:
• Task• Extension• Plugin
@tsmith
![Page 38: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/38.jpg)
Taskclass CreatePropertiesFileTask extends DefaultTask { @TaskAction void createFile() { Properties properties = new Properties() keys?.each { properties.put(it, getProp(it)) } outputFile?.withOutputStream { properties.store(it, "") } }}
@tsmith
![Page 39: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/39.jpg)
Task in Javatry { Properties properties = new Properties(); if (keys != null) { for (String key : keys) { properties.put(key, getProp(key)); } } if (keyFile != null) { FileOutputStream fileOutputStream = new FileOutputStream(keyFile); properties.store(fileOutputStream, ""); }} catch (FileNotFoundException fe) { throw new GradleScriptException("Error", fe);} catch (IOException ie) { throw new GradleScriptException("Error", ie);}
@tsmith
![Page 40: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/40.jpg)
Task// Properties properties = new Properties(); // for (String key : keys) { properties.put(key, getProp(key)); } // // FileOutputStream fileOutputStream = new FileOutputStream(keyFile); properties.store(fileOutputStream, ""); //// //// //
@tsmith
![Page 41: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/41.jpg)
Taskclass CreatePropertiesFileTask extends DefaultTask { @Input List<String> keys @OutputFile File outputFile
...}
@tsmith
![Page 42: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/42.jpg)
Extensionclass PropertyHolderExtension {
List<String> keys = [] File customPropertiesFile Project project
PropertyHolderExtension(Project project) { this.project = project }
@tsmith
![Page 43: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/43.jpg)
Extensionclass KeyHolderExtension { ... void keyFile(String filename) { keyFile = new File(filename) }
def getProp(String key) { if (System.properties.get(key) != null) { return System.properties.get(key) } else if (project.hasProperty(key)) { ...
@tsmith
![Page 44: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/44.jpg)
Pluginclass PropertyHolderPlugin implements Plugin<Project> {
@Override void apply(Project project) { def propertyHolder = project.extensions.create( "propertyHolder", PropertyHolderExtension, project)
@tsmith
![Page 45: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/45.jpg)
Plugin//Example 1. Without configuredef propertyHolder = project.extensions.create(...)
//Example 2. With configureproject.configure(project) { def propertyHolder = extensions.create(...)
@tsmith
![Page 46: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/46.jpg)
Pluginproject.configure(project) { ... afterEvaluate { if (!propertyHolder.keys.isEmpty()) { project.tasks.create("createCustomPropertiesFile", CreatePropertiesFileTask) { it.keyFile = propertyHolder.customPropertiesFile it.keys = propertyHolder.keys } } } ...
@tsmith
![Page 47: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/47.jpg)
Consuming the pluginapply 'custom-properties'
propertyHolder{ keys = 'CONSUMER_KEY',... keyFile 'custom.properties'}
@tsmith
![Page 48: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/48.jpg)
Kotlin Version - Taskopen class CreatePropertiesFileTask() : DefaultTask() { @Input var keys: List<String> = ArrayList()
@OutputFile var keyFile: File? = null
@tsmith
![Page 49: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/49.jpg)
Kotlin Version - Task@TaskActionfun createFile() { val properties = Properties() for (key in keys) { properties.put(key, getProp(key)) }
val fileOutputStream = FileOutputStream(keyFile)
properties.store(fileOutputStream, "")}
@tsmith
![Page 50: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/50.jpg)
Kotlin Version - Task@TaskActionfun createFile() { val properties = Properties()
keys.forEach { key -> properties.put(key, getProp(key)) }
properties.store(keyFile!!.outputStream(), "")}
@tsmith
![Page 51: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/51.jpg)
Extension - Kotlin versiondata class PropertyHolderExtension(val project: Project, var keys: List<String> = ArrayList(), var customFile: File? = null) {
}
@tsmith
![Page 52: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/52.jpg)
Plugin - Kotlin Versionclass PropertyHolderPlugin : Plugin<Project> { override fun apply(project: Project) { project.extensions .add("kotlinHolder",PropertyHolderExtension(project)) }}
@tsmith
![Page 53: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/53.jpg)
Plugin - Kotlin Versionclass PropertyHolderPlugin : Plugin<Project> { override fun apply(project: Project) { project.extensions.add("kotlinHolder", PropertyHolderExtension(project))
project.afterEvaluate { project -> val extension = project.extensions.getByName("kotlinHolder") as PropertyHolderExtension } }}
@tsmith
![Page 54: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/54.jpg)
Sprinkle it with Extension Functionsfun Project.configure(exec: Project.() -> Unit) = exec()
fun Project.extensions(exec: ExtensionContainer.() -> Unit) = extensions.exec()
fun Project.propertyHolder() = extensions.getByName("kotlinHolder") as PropertyHolderExtension
@tsmith
![Page 55: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/55.jpg)
Kotlin Version - Plugin//beforeproject.extensions .add("kotlinHolder", PropertyHolderExtension(project))
//afterproject.configure { extensions { add("kotlinHolder", PropertyHolderExtension(project)) }}
@tsmith
![Page 56: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/56.jpg)
Kotlin Version - Pluginproject.configure { extensions { add("kotlinHolder", PropertyHolderExtension(project)) } afterEvaluate { project -> if (!propertyHolder().keys.isEmpty()) { tasks.create("createPropertiesFile", CreatePropertiesFileTask::class.java) { task -> task.keys = propertyHolder().keys task.keyFile = propertyHolder().customFile!! } } }}
@tsmith
![Page 57: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/57.jpg)
Resources• Kotlin docs• Kotlin Koans• Anko• Gradle Script Kotlin• Advancing Android Development with the Kotlin Language• Gradle Kotlin Demo
@tsmith
![Page 58: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/58.jpg)
Thanks!Ty Smith
@tsmith
![Page 59: But I like Java! - GOTO Conference · "I call it my billion-dollar mistake... [which] has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused](https://reader034.vdocuments.mx/reader034/viewer/2022042311/5ed8cc856714ca7f47689612/html5/thumbnails/59.jpg)
@tsmith