Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ohefny/1b6a075957cfb4ed1127052dbe32ac98 to your computer and use it in GitHub Desktop.

Select an option

Save ohefny/1b6a075957cfb4ed1127052dbe32ac98 to your computer and use it in GitHub Desktop.
Passing dynamic object through chains ( like RxJava )

There are times when you're using chaining and you want to pass all the every chain result to the last chain without creating redundant types that will be only used once inside these chains
Note:: You can always do that by nesting chains which looks ugly

One Data Class with nullable members or default valued

This can also be achieved without copying using one data class with mutable members

data class Info(val id:Int?=null,val name:String="", val country:String?=null)
fun main(){
    
     Single.just(1).map {Info(id=1) }
            .flatMap {params-> Single.just("Ahmed").map { params.copy(name=it) } }
            .flatMap { params->Single.just("Egypt").map { params.copy(country=it)} }
            .subscribe {params->
             print(params.country!!)
             print(params.name)
            }        
  
}

Pros ::


  • Most readable and clean approach
  • Can return the type outside of the function scope if the data class

Cons ::

  • If you're returning unrelevant data through the chain your class will have no meaning
  • If you don't want to return all the chains results and each chain should return different mix of types you may need to declare multiple classes
  • You will have to write the class declaration upfront

Dynamic Objects Using Maps

Making generic object with named variables of mutliple types using map collection
You can use Kotlin 'to' infix function to creat Pair or you can make your own function to force the key type to be string which you can see in 'eq' function

typealias NamedEntry = Pair<String,Any>
typealias DynamicObj = MutableMap<String,Any>

infix fun String.eq(value:Any):NamedEntry = NamedEntry(this,value)
infix fun NamedEntry.with(other:NamedEntry):DynamicObj = mutableMapOf(this,other)
infix fun DynamicObj.with(other:NamedEntry):DynamicObj {
    this[other.first]=other.second
    return this
}
fun <T> DynamicObj.valueOf(key:String):T = this[key]!! as T

fun main(){
    var map=("age" to 25) with ("name" to "Ahmed") with ("country" to "Egypt")
    map with ("id" to 1000)
    print(map.valueOf<String>("name"))
    print(map.valueOf<Int>("age"))
    
    
    Single.just(1).map { ("id" eq it) }
        .flatMap {params-> Single.just("Ahmed").map { params.with("name" eq it) } }
        .flatMap { params->Single.just("Egypt").map { params.with("country" eq it) } }
        .subscribe {params->
            print(params.valueOf<String>("name"))
            print(params.valueOf<Int>("id"))
        }
  
}

Pros ::

  • No need to declare the type upfront just append the data to the map
  • Returning different result for each chain is not an issue

Cons ::

  • Extracting variables is not type safe
  • No AutoCompletion for finding variables
  • Any typo in the key of the map won't be noticed until the app crashes
  • Returning the dynamic object as result of a function outside chains scope .. Make it ambigous of which key's are used

Singelton Object ( object keyword )


Kotlin provide object keyword which make it easier to extend

fun main(){
    Single.just(1)
        .flatMap {id-> Single.just("Ahmed").map { object{val name =it ; val id = id} }
        .flatMap { params->Single.just("Egypt").map { object{val name =params.name; val id = params.id; val country=it}
        .subscribe {params->
            print(params.name)
            print(params.id)
        }
}

Pros ::

  • it solves all the proplems of the first approach

Cons ::

  • Same problem with returning the type out side of the scope as this type won't be available outside of the chain scope .. we can use the same solution
  • You have to redeclare the objects fields every time you want to append new member to it