├── .editorconfig ├── .gitignore ├── .idea ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── _config.yml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── jcmsalves │ │ └── kotlinplayground │ │ ├── MainActivity.kt │ │ ├── dataclasses │ │ ├── Person.kt │ │ ├── PersonJava.java │ │ ├── autovalue │ │ │ ├── CallingCode.java │ │ │ ├── OverloadedPerson.kt │ │ │ └── PersonAutoValue.java │ │ ├── defaultsandcopy │ │ │ └── Person.kt │ │ └── inheritance │ │ │ └── Person.kt │ │ ├── parcelable │ │ ├── ActivityA.kt │ │ ├── ActivityB.kt │ │ ├── Person.kt │ │ └── PersonParcelize.kt │ │ ├── runtimechecks │ │ ├── SomeActivity.kt │ │ └── SomeActivityJava.java │ │ ├── sealedclasses │ │ ├── BasicScreenStateJava.java │ │ ├── KotlinEnums.kt │ │ ├── ScreenState.kt │ │ └── SomeData.kt │ │ ├── standardfunctions │ │ └── StandardFunctions.kt │ │ ├── syntax │ │ ├── Classes.kt │ │ ├── ConditionalExpressions.kt │ │ ├── Functions.kt │ │ ├── Nullability.kt │ │ ├── Ranges.kt │ │ ├── SemiColon.kt │ │ ├── SmartCasts.kt │ │ ├── Variables.kt │ │ └── When.kt │ │ └── trywithresources │ │ ├── Use.java │ │ └── Use.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ └── activity_some.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── default-detekt-config.yml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | [*.{kt,kts}] 3 | insert_final_newline= true 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/ 38 | 39 | # Keystore files 40 | # Uncomment the following line if you do not want to check your keystore files in. 41 | #*.jks 42 | 43 | # External native build folder generated in Android Studio 2.2 and later 44 | .externalNativeBuild 45 | 46 | # Google Services (e.g. APIs or Firebase) 47 | google-services.json 48 | 49 | # Freeline 50 | freeline.py 51 | freeline/ 52 | freeline_project_description.json -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Joao Alves 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kotlin-playground 2 | Kotlin Android samples/template project 3 | 4 | This project is basically a repo of Kotlin Android Samples to support my [Kotlin Playground Series](https://medium.com/@jcmsalves/kotlin-playground-aab8be8ac432 "Kotlin Playground") on Medium. The goal with the series is that at the end we either have a new nice kotlin template project or just a bunch of useful samples that people can easily pick up. 5 | 6 | The idea is that the project grows with each article published so I'll tag each article release with article_# in the repo so it's easier to access the code for each article. 7 | 8 | ---- 9 | 10 | ### Articles Index 11 | 1. [Android and Kotlin — basic Hello World](https://joaoalves.dev/posts/kotlin-playground/android-and-kotlinbasic-hello-world "Android and Kotlin — basic Hello World") 12 | 13 | 2. [Kotlin Syntax Part I — why am I excluded?](https://joaoalves.dev/posts/kotlin-playground/kotlin-syntax-part-i-why-am-i-excluded "Kotlin Syntax Part I — why am I excluded?") 14 | 15 | 3. [Kotlin Syntax Part II — when did this switch happen?](https://joaoalves.dev/posts/kotlin-playground/kotlin-syntax-part-ii-when-did-this-switch-happen "Kotlin Syntax Part II — when did this switch happen?") 16 | 17 | 4. [Kotlin data classes — enough boilerplate](https://joaoalves.dev/posts/kotlin-playground/kotlin-data-classes-enough-boilerplate "Kotlin data classes — enough boilerplate") 18 | 19 | 5. [Parcelable in Kotlin? Here comes Parcelize](https://joaoalves.dev/posts/kotlin-playground/parcelable-in-kotlin-here-comes-parcelize "Parcelable in Kotlin? Here comes Parcelize") 20 | 21 | 6. [Kotlin Sealed Classes —  enums with swag](https://joaoalves.dev/posts/kotlin-playground/kotlin-sealed-classes-enums-with-swag "Kotlin Sealed Classes —  enums with swag") 22 | 23 | 7. [Kotlin Static Analysis — why and how?](https://joaoalves.dev/posts/kotlin-playground/kotlin-static-analysis-why-and-how "Kotlin Static Analysis — why and how?") 24 | 25 | 8. [Kotlin backend? Yes it's possible](https://joaoalves.dev/posts/kotlin-playground/kotlin-backend-yes-its-possible "Kotlin backend? Yes it's possible") 26 | 27 | 9. [Kotlin standard functions — just another guide](https://joaoalves.dev/posts/kotlin-playground/kotlin-standard-functions-just-another-guide "Kotlin standard functions — just another guide") 28 | 29 | 10. [Kotlin runtime checks — require and check](https://joaoalves.dev/posts/kotlin-playground/kotlin-runtime-checks-require-and-check "Kotlin runtime checks — require and check") 30 | 31 | 11. [Kotlin try-with-resources — use](https://joaoalves.dev/posts/kotlin-playground/kotlin-trywithresources-use "Kotlin try-with-resources — use") 32 | 33 | 12. [Kotlin Playground — finish line](https://joaoalves.dev/posts/kotlin-playground/kotlin-playground-finish-line "Kotlin Playgrond - finish line") 34 | 35 | ---- 36 | 37 | If you have any cool ideas or suggestions feel free to open issues in the repo and I'll try to address in a future article. 38 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 26 7 | defaultConfig { 8 | applicationId "com.jcmsalves.kotlinplayground" 9 | minSdkVersion 21 10 | targetSdkVersion 26 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | packagingOptions { 22 | exclude 'META-INF/*' 23 | } 24 | 25 | buildToolsVersion '26.0.2' 26 | } 27 | 28 | repositories { 29 | jcenter() 30 | mavenCentral() 31 | maven { url "http://dl.bintray.com/kotlin/ktor" } 32 | maven { url "https://dl.bintray.com/kotlin/kotlinx" } 33 | } 34 | 35 | configurations { 36 | ktlint 37 | } 38 | 39 | dependencies { 40 | implementation fileTree(include: ['*.jar'], dir: 'libs') 41 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 42 | implementation 'com.android.support:appcompat-v7:26.1.0' 43 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 44 | implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.40' 45 | 46 | // AutoValue 47 | compileOnly "com.google.auto.value:auto-value:1.5" 48 | annotationProcessor "com.google.auto.value:auto-value:1.5" 49 | 50 | // ktlint 51 | ktlint "com.github.shyiko:ktlint:0.15.0" 52 | 53 | testImplementation 'junit:junit:4.12' 54 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 55 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 56 | 57 | // ktor 58 | compile "io.ktor:ktor:$ktor_version" 59 | compile "io.ktor:ktor-server-netty:$ktor_version" 60 | } 61 | 62 | task ktlint(type: JavaExec, group: "verification") { 63 | description = "Check Kotlin code style." 64 | classpath = configurations.ktlint 65 | main = "com.github.shyiko.ktlint.Main" 66 | args "src/**/*.kt" 67 | //args "--reporter=checkstyle,output=${buildDir}/ktlint.xml" 68 | } 69 | check.dependsOn ktlint 70 | 71 | androidExtensions { 72 | experimental = true 73 | } 74 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | import io.ktor.application.call 6 | import io.ktor.http.ContentType 7 | import io.ktor.response.respondText 8 | import io.ktor.routing.get 9 | import io.ktor.routing.routing 10 | import io.ktor.server.engine.embeddedServer 11 | import io.ktor.server.netty.Netty 12 | import kotlinx.android.synthetic.main.activity_main.* 13 | 14 | class MainActivity : AppCompatActivity() { 15 | 16 | override fun onCreate(savedInstanceState: Bundle?) { 17 | super.onCreate(savedInstanceState) 18 | setContentView(R.layout.activity_main) 19 | 20 | updateTextButton.setOnClickListener { 21 | runServer() 22 | } 23 | } 24 | 25 | fun runServer() { 26 | val jsonResponse = """{ 27 | "id": 1, 28 | "name": "Joao Alves", 29 | "username": "joao.alves", 30 | "email": "joao.alves@example.com" 31 | }""" 32 | 33 | embeddedServer(Netty, 8080) { 34 | routing { 35 | get("/") { 36 | call.respondText(jsonResponse, ContentType.Application.Json) 37 | } 38 | 39 | get("/random") { 40 | call.respondText("random message", ContentType.Text.Html) 41 | } 42 | } 43 | }.start(wait = true) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/Person.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses 2 | 3 | data class Person(val name: String, val age: Int, val email: String, val phone: Long) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/PersonJava.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses; 2 | 3 | public final class PersonJava { 4 | 5 | private final String name; 6 | private final int age; 7 | private final String email; 8 | private final long phone; 9 | 10 | public PersonJava(String name, int age, String email, long phone) { 11 | this.name = name; 12 | this.age = age; 13 | this.email = email; 14 | this.phone = phone; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public int getAge() { 22 | return age; 23 | } 24 | 25 | public String getEmail() { 26 | return email; 27 | } 28 | 29 | public long getPhone() { 30 | return phone; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "PersonJava{" + 36 | "name='" + name + '\'' + 37 | ", age=" + age + 38 | ", email='" + email + '\'' + 39 | ", phone=" + phone + 40 | '}'; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) { 46 | return true; 47 | } 48 | if (o == null || getClass() != o.getClass()) { 49 | return false; 50 | } 51 | 52 | PersonJava that = (PersonJava) o; 53 | 54 | if (age != that.age) { 55 | return false; 56 | } 57 | if (phone != that.phone) { 58 | return false; 59 | } 60 | if (name != null ? !name.equals(that.name) : that.name != null) { 61 | return false; 62 | } 63 | return email != null ? email.equals(that.email) : that.email == null; 64 | } 65 | 66 | @Override 67 | public int hashCode() { 68 | int result = name != null ? name.hashCode() : 0; 69 | result = 31 * result + age; 70 | result = 31 * result + (email != null ? email.hashCode() : 0); 71 | result = 31 * result + (int) (phone ^ (phone >>> 32)); 72 | return result; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/autovalue/CallingCode.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses.autovalue; 2 | 3 | import com.jcmsalves.kotlinplayground.dataclasses.Person; 4 | 5 | public class CallingCode { 6 | 7 | PersonAutoValue personAutoValue = PersonAutoValue.builder() 8 | .setName("name") 9 | .setEmail("email@gmail.com") 10 | // .setAge(32) - not mandatory 11 | .setPhone(1234567890) 12 | .build(); 13 | 14 | Person person = new Person("name", 32, "email@gmail.com", 1234567890); 15 | 16 | OverloadPerson overloadPerson1 = new OverloadPerson("name", 32, "email@gmail.com", 1234567890); 17 | OverloadPerson overloadPerson2 = new OverloadPerson("name", 32, "email@gmail.com"); 18 | OverloadPerson overloadPerson3 = new OverloadPerson("name", 32); 19 | OverloadPerson overloadPerson4 = new OverloadPerson("name"); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/autovalue/OverloadedPerson.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses.autovalue 2 | 3 | data class OverloadPerson @JvmOverloads constructor(val name: String = "some name", 4 | val age: Int = 25, 5 | val email: String = "some email", 6 | val phone: Long = 1234) 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/autovalue/PersonAutoValue.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses.autovalue; 2 | 3 | import com.google.auto.value.AutoValue; 4 | 5 | @AutoValue 6 | public abstract class PersonAutoValue { 7 | 8 | public abstract String getName(); 9 | 10 | public abstract int getAge(); 11 | 12 | public abstract String getEmail(); 13 | 14 | public abstract int getPhone(); 15 | 16 | public static Builder builder() { 17 | return new AutoValue_PersonAutoValue.Builder() 18 | .setAge(30); 19 | } 20 | 21 | @AutoValue.Builder 22 | public abstract static class Builder { 23 | 24 | public abstract Builder setName(String newName); 25 | 26 | public abstract Builder setAge(int newAge); 27 | 28 | public abstract Builder setEmail(String newEmail); 29 | 30 | public abstract Builder setPhone(int newPhone); 31 | 32 | public abstract PersonAutoValue build(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/defaultsandcopy/Person.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses.defaultsandcopy 2 | 3 | data class Person(val name: String = "default name", val age: Int = 30, 4 | val email: String = "dummy email", val phone: Long = 1234567890) 5 | 6 | val person1: Person = Person("name", 25, "email@gmail.com", 555544448) 7 | 8 | val person2: Person = Person() 9 | 10 | val person3: Person = Person("name", 25) 11 | 12 | val person4: Person = Person(name = "name", phone = 9876543210) 13 | 14 | val person1Copy = person1.copy() 15 | 16 | val person1With30 = person1.copy(age = 30) 17 | 18 | val person4WithEmail = person4.copy(email = "person4@gmail.com") 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/dataclasses/inheritance/Person.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.dataclasses.inheritance 2 | 3 | interface Person { 4 | val name: String 5 | val age: Int 6 | val email: String 7 | 8 | fun hasResponsibilities(): Boolean 9 | } 10 | 11 | data class Adult(override val name: String, override val age: Int, override val email: String) : Person { 12 | val isMarried: Boolean = false 13 | val hasKids: Boolean = false 14 | override fun hasResponsibilities(): Boolean = true 15 | } 16 | 17 | data class Child(override val name: String, override val age: Int, override val email: String = "") : Person { 18 | override fun hasResponsibilities(): Boolean = false 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/parcelable/ActivityA.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.parcelable 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.os.Bundle 6 | 7 | class ActivityA : Activity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | 12 | val intent = Intent(this, ActivityB::class.java) 13 | val person = Person("name", 32, "email@email.com", 1234) 14 | 15 | intent.putExtra("A_STRING", "some string") 16 | intent.putExtra("A_NUMBER", 1234) 17 | intent.putExtra("AN_OBJECT", person) 18 | 19 | startActivity(intent) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/parcelable/ActivityB.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.parcelable 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | 5 | class ActivityB : AppCompatActivity() 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/parcelable/Person.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.parcelable 2 | 3 | import android.os.Parcel 4 | import android.os.Parcelable 5 | 6 | data class Person(val name: String, val age: Int, val email: String, val phone: Long) : Parcelable { 7 | constructor(parcel: Parcel) : this( 8 | parcel.readString(), 9 | parcel.readInt(), 10 | parcel.readString(), 11 | parcel.readLong()) 12 | 13 | override fun writeToParcel(parcel: Parcel, flags: Int) { 14 | parcel.writeString(name) 15 | parcel.writeInt(age) 16 | parcel.writeString(email) 17 | parcel.writeLong(phone) 18 | } 19 | 20 | override fun describeContents(): Int { 21 | return 0 22 | } 23 | 24 | companion object CREATOR : Parcelable.Creator { 25 | override fun createFromParcel(parcel: Parcel): Person { 26 | return Person(parcel) 27 | } 28 | 29 | override fun newArray(size: Int): Array { 30 | return arrayOfNulls(size) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/parcelable/PersonParcelize.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.parcelable 2 | 3 | import android.os.Parcelable 4 | import kotlinx.android.parcel.Parcelize 5 | 6 | @Parcelize 7 | data class PersonParcelize(val name: String, 8 | val age: Int, 9 | val email: String, 10 | val phone: Long) : Parcelable 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/runtimechecks/SomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.runtimechecks 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | 6 | class SomeActivity : AppCompatActivity() { 7 | 8 | companion object { 9 | private const val SOME_EXTRA_KEY = "some_extra_key" 10 | } 11 | 12 | private var isRefreshing = false 13 | 14 | public override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | require(intent.extras.containsKey(SOME_EXTRA_KEY), { 17 | "SOME_EXTRA is required to launch SomeActivity" 18 | }) 19 | 20 | val passedArgument = intent.extras.getString(SOME_EXTRA_KEY) 21 | // do something with passed argument 22 | refreshSomething() 23 | } 24 | 25 | private fun refreshSomething() { 26 | require(!isRefreshing, { 27 | "Trying to refresh state while already refreshing" 28 | }) 29 | 30 | isRefreshing = true 31 | // do something that requires a valid state 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/runtimechecks/SomeActivityJava.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.runtimechecks; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.util.Log; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | public class SomeActivityJava extends AppCompatActivity { 9 | 10 | private static final String SOME_EXTRA_KEY = "some_extra_key"; 11 | private boolean isRefreshing = false; 12 | 13 | @Override 14 | public void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | 17 | if (!getIntent().getExtras().containsKey(SOME_EXTRA_KEY)) { 18 | finish(); 19 | } 20 | 21 | String passedArgument = getIntent().getExtras().getString(SOME_EXTRA_KEY); 22 | // do something with passed argument 23 | 24 | refreshSomething(); 25 | 26 | } 27 | 28 | private void refreshSomething() { 29 | if (isRefreshing) { 30 | return; 31 | } 32 | 33 | isRefreshing = true; 34 | // do something that requires a valid state 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/sealedclasses/BasicScreenStateJava.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.sealedclasses; 2 | 3 | public enum BasicScreenStateJava { 4 | ERROR, 5 | LOADING, 6 | DATA 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/sealedclasses/KotlinEnums.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.sealedclasses 2 | 3 | enum class BasicScreenState { 4 | ERROR, 5 | LOADING, 6 | DATA 7 | } 8 | 9 | enum class ScreenStateField(val someData: SomeData) { 10 | ERROR(SomeData("1", "some data 1")), 11 | LOADING(SomeData("2", "some data 2")), 12 | DATA(SomeData("3", "some data 3")) 13 | } 14 | 15 | fun setBasicScreenState(basicScreenState: BasicScreenState) { 16 | when (basicScreenState) { 17 | BasicScreenState.ERROR -> { /* set error state in the view */ } 18 | BasicScreenState.LOADING -> { /* set loading state in the view */ } 19 | BasicScreenState.DATA -> { /* hide loading or error states in the view */ } 20 | } 21 | } 22 | 23 | fun displayData(someData: SomeData) { 24 | // actually display the data in the view 25 | //sometextView.text = someData.name 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/sealedclasses/ScreenState.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.sealedclasses 2 | 3 | sealed class ScreenState { 4 | class Error : ScreenState() 5 | class Loading : ScreenState() 6 | data class Data(val someData: SomeData) : ScreenState() 7 | } 8 | 9 | fun setScreenState(screenState: ScreenState) { 10 | when (screenState) { 11 | is ScreenState.Loading -> { /* set loading state in the view */ } 12 | is ScreenState.Data -> { 13 | /* hide loading or error states in the view and display data*/ 14 | //sometextView.text = screenState.someData.name 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/sealedclasses/SomeData.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.sealedclasses 2 | 3 | data class SomeData(val id: String, val name: String) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/standardfunctions/StandardFunctions.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.standardfunctions 2 | 3 | data class SomeObject(var someField: String = "some default value", var otherField: Int = 55) 4 | 5 | class StandardFunctions { 6 | 7 | fun playground() { 8 | var someObject = SomeObject() 9 | 10 | val letExample = someObject?.let { 11 | print(it.someField) 12 | this.someOtherFunction() 13 | "some result" 14 | } 15 | 16 | val applyExample = someObject.apply { 17 | someField = "some field" 18 | this.otherField = 99 19 | "some result" 20 | } 21 | 22 | 23 | val runExample = someObject.run { 24 | print(someField) 25 | this.otherField = 99 26 | "some result" 27 | } 28 | 29 | val alsoExample = someObject.also { 30 | print(it.someField) 31 | this.someOtherFunction() 32 | "some result" 33 | } 34 | 35 | val withExample = with(someObject) { 36 | print(someField) 37 | this.otherField = 99 38 | "some result" 39 | } 40 | } 41 | 42 | fun someOtherFunction() { 43 | print("random message") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/Classes.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | import java.time.LocalDateTime 4 | 5 | class ClassWithEmptyBody 6 | 7 | class ClassWithBody(val name: String) { 8 | val nameLength = name.length 9 | } 10 | 11 | class ClassWithoutConstructorKeyword (val name: String) { 12 | val nameLength = name.length 13 | } 14 | 15 | class ClassWithConstructorKeyword constructor (val name: String) { 16 | val nameLength = name.length 17 | } 18 | 19 | class ClassWithAccessModifier public constructor (val name: String) { 20 | val nameLength = name.length 21 | } 22 | 23 | class ClassWithInitialization public constructor (val name: String) { 24 | val nameLength: Int 25 | 26 | init { 27 | nameLength = name.length 28 | } 29 | } 30 | 31 | class ClassWithMultipleConstructors (val name: String) { 32 | val nameLength = name.length 33 | 34 | constructor(name: String, age: Int) : this(name) { 35 | val yearOfBirth = LocalDateTime.now().year - age 36 | } 37 | } 38 | 39 | class Instantiations { 40 | val ClassWithEmptyBody = ClassWithEmptyBody() 41 | 42 | val ClassWithBody = ClassWithBody("a name") 43 | } 44 | 45 | open class ParentClass (someNumber: Int) 46 | 47 | class ChildClass (someNumber: Int) : ParentClass(someNumber) 48 | 49 | interface InterfaceExample { 50 | fun test() 51 | } 52 | 53 | class InterfaceImplementation : InterfaceExample { 54 | override fun test() { 55 | //Some implementation 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/ConditionalExpressions.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | class ConditionalExpressions { 4 | 5 | fun biggestWord(someWord: String, anotherWord: String): String { 6 | if (someWord.length > anotherWord.length) { 7 | return someWord 8 | } else { 9 | return anotherWord 10 | } 11 | } 12 | 13 | fun biggestWordOneLine(someWord: String, anotherWord: String): String { 14 | return if (someWord.length > anotherWord.length) someWord else anotherWord 15 | } 16 | 17 | fun biggestWordAsExpression(someWord: String, anotherWord: String) = 18 | if (someWord.length > anotherWord.length) someWord else anotherWord 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | fun aFunction(x: Int, y: Int): Int { 4 | return x + y 5 | } 6 | 7 | fun aFunctionWithExplicitReturnType(x: Int, y: Int) { 8 | println("sum of $x and $y is ${x + y}") 9 | } 10 | 11 | fun aFunctionWithoutReduntant(x: Int, y: Int) { 12 | println("sum of $x and $y is ${x + y}") 13 | } 14 | 15 | fun aFunctionAsExpression(x: Int, y: Int) = x + y 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/Nullability.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | class Nullability { 4 | 5 | fun NonNullString() { 6 | var nonNullString: String = "some string" 7 | // nonNullString = null // compilation error 8 | } 9 | 10 | fun NullString() { 11 | var nullString: String? = "some string" 12 | nullString = null // nothing wrong 13 | } 14 | 15 | fun SafeCase() { 16 | var nullString: String? = "some string" 17 | var length: Int 18 | var lengthOrNull: Int? 19 | 20 | // nullString.length // compilation error 21 | // length = nullString?.length // compilation error 22 | lengthOrNull = nullString?.length 23 | } 24 | 25 | fun ElvisOperator() { 26 | var nullString: String? = "some string" 27 | var length: Int 28 | 29 | // nullString.length // compilation error 30 | length = nullString?.length ?: -1 31 | } 32 | 33 | fun NeverUseThis() { 34 | var nullString: String? = "please don't use this operator" 35 | val length = nullString!!.length 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/Ranges.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | class Ranges { 4 | 5 | fun simpleRange(number: Number) { 6 | if (number in 1..100) 7 | print(number) 8 | } 9 | 10 | fun simpleRangeReverseWrong() { 11 | for (number in 100..1) 12 | print(number) // this doesn't print anything 13 | } 14 | 15 | fun simpleRangeReverseCorrect() { 16 | for (number in 100 downTo 1) 17 | print(number) 18 | } 19 | 20 | fun until() { 21 | for (i in 1 until 100) { 22 | println(i) 23 | } 24 | } 25 | 26 | fun steps() { 27 | for (i in 1..100 step 2) { 28 | println(i) 29 | } 30 | 31 | for (i in 100 downTo 1 step 5) { 32 | println(i) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/SemiColon.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | enum class SemiColonNotRequired { 4 | WITH, 5 | WITHOUT 6 | } 7 | 8 | enum class SemiColonRequired { 9 | WITH, 10 | WITHOUT; 11 | 12 | fun isRequired(): Boolean = this == WITH 13 | } 14 | 15 | fun semicolon() { 16 | var list = 1..10 17 | list.forEach { val result = it * 2; println("$it times 2 is $result") } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/SmartCasts.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | class SmartCasts { 4 | 5 | fun simple(value: Any) { 6 | if (value is Int) { 7 | print(value == 0) // value is automatically cast to Int 8 | } 9 | } 10 | 11 | fun withReturn(value: Any) { 12 | if (value !is Int) return 13 | print(value == 0) // value is automatically cast to Int 14 | } 15 | 16 | fun withOr(value: Any) { 17 | // value is automatically cast to Int on the right-hand side of `||` 18 | if (value !is Int || value == 0) return 19 | } 20 | 21 | fun withAnd(value: Any) { 22 | // value is automatically cast to Int on the right-hand side of `&&` 23 | if (value is Int && value > 1) { 24 | print(value > 1) // value is automatically cast to Int 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/Variables.kt: -------------------------------------------------------------------------------- 1 | import java.time.LocalDateTime 2 | 3 | fun Variables() { 4 | 5 | val immediateAssignment: Int = 1 6 | 7 | val inferredTypeInt = 2 8 | 9 | val deferredAssignment: Int 10 | deferredAssignment = 3 11 | 12 | var mutableInferredTypeString = "some string" 13 | mutableInferredTypeString += "some concat" 14 | } 15 | 16 | class MutableValExample(val yearOfBirth: Int) { 17 | val age: Int 18 | get() = LocalDateTime.now().year - yearOfBirth 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/syntax/When.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.syntax 2 | 3 | class When { 4 | 5 | fun describe(obj: Any): String = 6 | when (obj) { 7 | 1 -> "One" 8 | "Hello" -> "Greeting" 9 | is Long -> "Long" 10 | !is String -> "Not a string" 11 | else -> "Unknown" 12 | } 13 | 14 | fun ifelseif() { 15 | var number = 234 16 | 17 | // traditional if-else-if chain 18 | if (number > 0) { 19 | print("number is bigger than 0") 20 | } else if (number < 0) { 21 | print("number is lower than 0") 22 | } else { 23 | print("number is 0") 24 | } 25 | 26 | // using when to replace the above chain 27 | when { 28 | number > 0 -> print("number is bigger than 0") 29 | number < 0 -> print("number is lower than 0") 30 | else -> print("number is 0") 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/trywithresources/Use.java: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.trywithresources; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | 8 | public class Use { 9 | 10 | private String readFirstLine() throws FileNotFoundException { 11 | BufferedReader reader = new BufferedReader(new FileReader("test.file")); 12 | try { 13 | return reader.readLine(); 14 | } catch (IOException e) { 15 | e.printStackTrace(); 16 | } finally { 17 | try { 18 | reader.close(); 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/jcmsalves/kotlinplayground/trywithresources/Use.kt: -------------------------------------------------------------------------------- 1 | package com.jcmsalves.kotlinplayground.trywithresources 2 | 3 | import java.io.BufferedReader 4 | import java.io.FileReader 5 | 6 | private fun readFirstLineJava7(): String { 7 | BufferedReader(FileReader("test.file")).use { return it.readLine() } 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 |