https://kotlinlang.org logo
#android
Title
# android
a

Alin B.

07/26/2018, 12:02 PM
Let's say I have a class like
class Event(val actionId:Int, arg1:String, arg2: Int, arg3:MyClass, arg4:String)
but when I use the class, most likely I'll need
Event(actionID, oneOfTheArgs)
l

Lucas Ł

07/26/2018, 12:06 PM
imo they should be all separate classes with a common interface maybe a generic class?
class Event<T> (val actionId:Int, val arg:T)
for more arguments
class Event<T1, T2> (val actionId:Int, val arg1:T1, val arg2:T2)
etc...
a

Alin B.

07/26/2018, 12:11 PM
Very interesting, thank you very much
I also wonder if it wouldn't be simpler to have
class Event(actionId, bundle)
and put in bundle whatever I may need
l

Lucas Ł

07/26/2018, 12:12 PM
bundles are annoying because you need to keep keys, checking if values exist, etc.
a

Alin B.

07/26/2018, 12:12 PM
yeah, definitely a good point
what about moving all args into another class, so have
class Event(val actionId:Int, val args:ActionArgs)
l

Lucas Ł

07/26/2018, 12:14 PM
that works too, though you'd need more boilerplate code when compared to a generic class. Up to you 😉
👍 1
a

Alin B.

07/26/2018, 12:20 PM
I am pretty new to Kotlin. Is this the right syntax
open class Event<out T>(val action:Int, val arg:T)
?
c

Can Orhan

07/26/2018, 12:22 PM
Oh will each event only ever have 1 argument?
a

Alin B.

07/26/2018, 12:23 PM
no, it can have more than one, usually one
c

Can Orhan

07/26/2018, 12:25 PM
And do the receivers know which event they expect? Would something like this be acceptable?
Copy code
data class User(val userId: Int)
sealed class Event(actionId: Int) {
    data class EventA(val name: String): Event(1)
    data class EventB(val user: User, val someString: String): Event(2)
}
a

Alin B.

07/26/2018, 12:29 PM
Very interesting, learning someting new every day.
In code I'll have someting
Copy code
when(actionId){
               id1-> read params and do something
               id2 -> read params and do something
}
c

Can Orhan

07/26/2018, 12:32 PM
Yup! Or
Copy code
val event:Event = Event.EventA("fas")
when(event) {
    is Event.EventA -> {
        event.name
    }
    is Event.EventB -> {
        event.user.userId
    }
}
a

Alin B.

07/26/2018, 12:32 PM
coming from java, to me it looks like
Bundle
is the simplest way as it can have any number of params, but as mentioned above by Lukasz, there are keys that I need to remember
c

Can Orhan

07/26/2018, 12:33 PM
Yup but it's good to learn other patterns so that you can use plain-old-java or Kotlin without relying on the Android framework for bundles
👍 1
a

Alin B.

07/26/2018, 12:34 PM
Very, very interesting with sealed class, no need to rely on Bundle and also no need to remember keys. Let me give this a shoot
c

Can Orhan

07/26/2018, 12:35 PM
Good luck!
a

Alin B.

07/26/2018, 12:35 PM
Thank you very much for your time and valuable info!
Thank you both 👍
❤️ 1
c

Can Orhan

07/26/2018, 1:06 PM
Happy to help 🙏
a

Alin B.

07/26/2018, 1:07 PM
@Can Orhan if I have the Event used into another class
open class Interaction<out T>(...
which is used like
private val interactions= MutableLiveData<Interaction<Event>>()
then, I can't pass
Event.EventA
to Interaction as it expects
Event
type
c

Can Orhan

07/26/2018, 1:10 PM
Just created a scratch and the following works for me
Copy code
data class User(val userId: Int)
sealed class Event(actionId: Int) {
    data class EventA(val name: String): Event(1)
    data class EventB(val user: User, val someString: String): Event(2)
}
class Interaction<out T>(val thing: T)

val event:Event = Event.EventA("fas")
val interaction = Interaction<Event>(Event.EventA("Test"))
Are you use your events are extending the base event?
Specifically the colon here:
data class EventA(val name: String): Event(1)
a

Alin B.

07/26/2018, 1:18 PM
You are right, I did not extend the base event. In case if I don't have any params, I have
data class EventC():Event(3)
? Isn't this more resource intensive as it uses a empty class?
l

Lucas Ł

07/26/2018, 1:19 PM
Why wouldn't you use simple
Event
instead (if actionId is always required)
c

Can Orhan

07/26/2018, 1:20 PM
Sealed Class's init is private @Lucas Ł
😢 1
I know 😞
a

Alin B.

07/26/2018, 1:21 PM
yeah, just saw the error
this adds a lot of boilerplate code right? If I have 10 events without args, I need to make 10 classes, while for the other 2-3 events with more params, I have another 3 classes, ending in 13 vs
class Event(actionId, bundle)
c

Can Orhan

07/26/2018, 1:24 PM
I think if it improves the readability of your code, create the parameterless child. Especially if you're going to have multiple zero argument subclasses
a

Alin B.

07/26/2018, 1:24 PM
Am I missing something?
c

Can Orhan

07/26/2018, 1:25 PM
10 Events without args are arguably (no pun intended) more readable in code than
Event(actionId, null)
I'd rather see
CtaClickEvent()
and
CloseClickEvent()
instead of
Event(747)
and
Event(2112)
👆 2
a

Alin B.

07/26/2018, 6:25 PM
@Can Orhan sorry I had to step out. I agree, however if actionids are in a Enum, we could have
Event(Actions.TAKE_PICTURE)
so it's more readable. However, I agree,
Event(actionId, null)
does not look that well. I'll go on this path since it does indeed become very readable and does not depend on bundle.
and really, there should be rarely events without args
Today I learned something because of you. Thank you!
c

Can Orhan

07/26/2018, 6:29 PM
No problem. Happy to help 🙂
Event(Actions.TAKE_PICTURE)
Is certainly readable when creating the event but let's take the scenario where you want act on a list of different events. Suddenly, your simple
when
statement is going to have a case for Event(Int)` with an if statement over the different `actionId`s
a

Alin B.

07/26/2018, 6:34 PM
I don't understand what you mean with the when
but I like how it turned out
c

Can Orhan

07/26/2018, 8:06 PM
Sorry for the delay - What I was saying is that when you're acting on a list of event, you could end up with something like this:
Copy code
data class User(val userId: Int)
sealed class Event(val actionId: Int) {
    data class EventA(val name: String): Event(1)
    data class EventB(val user: User, val someString: String): Event(2)
    class GenericEvent: Event(3)
}
val user = User(3)
val eventsList = listOf(Event.EventA("Foo"), Event.EventB(user, "Bar"))

fun actOnEventUsingWith(event: Event) {
    when(event){
        is Event.EventA -> {
            //Do something
        }
        is Event.EventB -> {
            //Do something else
        }
        is Event.GenericEvent -> {
            if (event.actionId == 4) {
                //Hmmm
            } else if (event.actionId == 5) {
                //Hmmmmmmmm
            }
        }
    }
}
instead of
Copy code
fun actOnEventUsingWith(event: Event) {
    when(event){
        is Event.EventA -> {
            //Do something
        }
        is Event.EventB -> {
            //Do something else
        }
        is Event.BoringEvent -> {
            
        }
        is Event.AnotherEvent -> {

        }
    }
}
👍 1
a

Alin B.

07/27/2018, 8:27 AM
Yes, I get it. Thanks
👍 1