new functionality without having to inherit from the class. // 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. // 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. // 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>()
// 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
… // 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() } }
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
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>
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 // 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 }