new functionality without having to inherit from the class. https://kotlinlang.org/docs/referenc e/extensions.html // Extension Property val String.lastChar: Char = this[length - 1] // Extension Function fun Rectangle.getArea() { return length * width; } // DEMO fun usageDemo() { print(“Hello”.lastChar) // prints o val rect = Rectangle(2, 3) print(rect.getArea()) // prints 6 }
new functionality without having to inherit from that class. val Firebase.database = FirebaseDatabase.getInstance() val Firebase.firestore = FirebaseFirestore.getInstance() fun Firebase.firestore(app: FirebaseApp) = FirebaseFirestore.getInstance(app) // Usage: val firestore = Firebase.firestore val firestore2 = Firebase.firestore(app)
as a Higher-Order function. https://kotlinlang.org/docs/referenc e/inline-functions.html // from firebase-messaging-ktx inline fun remoteMessage( to: String, init: RemoteMessage.Builder.() -> Unit ): RemoteMessage { val builder = RemoteMessage.Builder(to) builder.init() return builder.build() } // Usage remoteMessage(“user1”) { messageId = “123” data = hashMapOf() }
as a parameter. https://kotlinlang.org/docs/referenc e/inline-functions.html#reified-typ e-parameters // from firebase-firestore inline fun <reified T> DocumentSnapshot.toObject(): T? = toObject(T::class.java) // Example val dataSnapshot = // … // Usage without Firebase KTX: dataSnapshot.toObject(Person::class.java) // Usage with Firebase KTX: dataSnapshot.toObject<Person>()
https://kotlinlang.org/docs/referenc e/multi-declarations.html // from firebase-storage-ktx operator fun UploadTask.TaskSnapshot.component1() = bytesTransferred operator fun UploadTask.TaskSnapshot.component2() = totalByteCount operator fun UploadTask.TaskSnapshot.component3() = metadata operator fun UploadTask.TaskSnapshot.component4() = uploadSessionUri
(instead of eagerly). https://kotlinlang.org/docs/referenc e/sequences.html // Create a Sequence from Realtime Database // values (From an Iterable) var snapshot: DataSnapshot val sequence = snapshot.children.asSequence() // Create a Sequence from Cloud Firestore // values (From an Iterator) var snapshot: QuerySnapshot val sequence = snapshot.iterator().asSequence()
fox jumps over the lazy dog".split(" ") val lengthsList = words.filter { println("filter: $it"); it.length > 3 } .map { println("length: ${it.length}"); it.length } .take(4) println("Lengths of first 4 words longer than 3 chars:") println(lengthsList) image from kotlinlang.org
fox jumps over the lazy dog".split(" ").asSequence() val lengthsSequence = wordsSequence.filter { println("filter: $it"); it.length > 3 } .map { println("length: ${it.length}"); it.length } .take(4) println("Lengths of first 4 words longer than 3 chars") println(lengthsSequence.toList()) // terminal operation image from kotlinlang.org
… // Coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' // Provides Extension Functions to use Coroutines with the Tasks API implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.9' }
{ try { val querySnapshot = usersRef.document("john").get().await() val johnUser = querySnapshot.toObject(User::class.java) val friendSnapshot = friendsRef.get().await() val friends = friendSnapshot.toObjects(Friend::class.java) showProfileAndFriends(johnUser, friends) } catch (e: FirebaseFirestoreException) { displayError(e) } } // Usage fun main() { GlobalScope.launch { // Avoid using GlobalScope. This is just an example loadUserData() } }
Computing using Sequences fun simple(): Sequence<Int> = sequence { for (i in 1..3) { Thread.sleep(100) // pretend we are computing it yield(i) // yield next value } } fun main() { simple().forEach { value -> println(value) } } // Blocks the main thread
Computing using suspend functions suspend fun simple(): List<Int> { delay(1000) // pretend we are computing it return listOf(1, 2, 3) } fun main() = runBlocking<Unit> { simple().forEach { value -> println(value) } } // Notice that we’re returning a List<Int>
Computing using Asynchronous Flow fun simple(): Flow<Int> = flow { for (i in 1..3) { delay(100) // pretend we are computing it emit(i) // emit next value } } fun main() = runBlocking<Unit> { // Collect the flow simple().collect { value -> println(value) } }
value can have one of the types from a limited set, but cannot have any other type https://kotlinlang.org/docs/referenc e/sealed-classes.html // Example sealed class Result { data class Success(val data: Int) : Result data class Error(val exception: Exception) : Result object InProgress : Result } // Usage fun handleResult(result: Result) { when (result) { is Result.Success -> { // do something with result.data } is Result.Error -> { // do something with result.exception } is Result.InProgress -> { // this one has no value passed to it } } }
Database. sealed class Child { data class Added(val dataSnapshot: DataSnapshot,val previousChildName: String?) : Child data class Changed(val dataSnapshot: DataSnapshot,val previousChildName: String?) : Child data class Removed(val dataSnapshot: DataSnapshot) : Child data class Moved(val dataSnapshot: DataSnapshot,val previousChildName: String?) : Child data class Cancelled(val databaseError: DatabaseError) : Child }
Pair<String, Any>) { for ((key, value) in pairs) { when (value) { is Boolean -> setCustomKey(key, value) is Double -> setCustomKey(key, value) is Float -> setCustomKey(key, value) is Int -> setCustomKey(key, value) is Long -> setCustomKey(key, value) is String -> setCustomKey(key, value) else -> { throw IllegalArgumentException("Illegal value type for key \"$key\"") } } } }