https://kotlinlang.org logo
#android-architecture
Title
# android-architecture
g

ghedeon

02/18/2019, 10:07 PM
For quite a while I was using the wrapper around the string resource. In order to delay context involvement. Ex: you have a string int, plus some params for the format, but you're not ready to pull the actual value, because it requires the context. So you delay it with a wrapper.
Copy code
class StringResource private constructor(
    val string: String?,
    @StringRes val stringRes: Int?,
    vararg val args: Any?
) {
    constructor(@StringRes stringRes: Int, vararg args: Any? = emptyArray()) : this(null, stringRes, args)

    constructor(string: String) : this(string, null, null)

    fun resolve(context: Context): String =
        if (stringRes != null) {
            context.getString(stringRes, args)
        } else requireNotNull(string)

  }
=============
Usage: 
ViewModel: StringResource(R.string.foo, arg1, arg2)
View: stringResource.resolve(context)
I'm wondering if other people do something similar and how their wrapper looks like.
👍 1
d

dewildte

02/18/2019, 10:11 PM
I would put this kind of thing inside a presenter. I always unit test my ViewModel and do not want anything platform specific inside or past the ViewModel. So a presenter seems like a fine place to do context necessary things.
most of the time though I think it's OK for the view to get the correct strings it needs to.
If I need the presenter for this kinda thing then have it observe a ViewState object on the ViewModel and do any string fetching or data mapping it needs to. The view could then observe the final data class and display it correctly.
My
ViewModel
usually gets it's
ViewState
objects from a
Channel
and posts them to a
LiveData<SpecificViewState>
. The
Presenter
uses a
MediatorLiveData<SpecificMappedViewState>
to map the ViewModels data to one containing the final result.
g

ghedeon

02/18/2019, 10:24 PM
You're right, the purpose of this class — to not have context in your ViewModel/Presenter. I guess that's clear. My question was more like: how your version of this class looks like, if you have any?. But yeah, thanks for the remarks.
r

russhwolf

02/19/2019, 1:52 AM
I’ve done a thing like this and liked it a lot. You can use a sealed class to clean it up a bit so you don’t need to have both
string
and
stringRes
as parameters. We also added
plurals
support on my current project. Not open-source unfortunately so I can’t share any code.
g

ghedeon

02/19/2019, 8:34 AM
Awesome! My thoughts exactly, about plurals as well. Thank you.
a

amadeu01

02/21/2019, 7:00 PM
@russhwolf is something like that
Copy code
sealed class StringResource(
    val string: String?,
    val stringRes: Int? = null,
    vararg val args: Any? = emptyArray())
{
    fun resolve(context: Context? = null): String =
        if (stringRes != null) {
            context?.getString(stringRes, args) ?: ""
        } else requireNotNull(string)
}

class StringRes(val i: Int, vararg val a: Any? = emptyArray()) : StringResource(null, i, a)
data class Pure(val s: String) : StringResource(s)


fun main() {
    println(Pure("Hello").resolve())
}
r

russhwolf

02/21/2019, 7:04 PM
Something like that. I wouldn't put
string
and
stringRes
in the base class. You can make
resolve()
abstract and have the subclasses contain only the fields they need and the implementation relevant to them. But that's mostly a style thing.
💯 1
s

sngrekov

02/21/2019, 8:52 PM
We have interface ResourceManager with methods like fun getString(res : Int) which we use in presenters, and concrete implementation AndroidResourceManager(val context : Context), which we inject into presenters.
✔️ 1
d

dewildte

02/21/2019, 9:12 PM
@sngrekov How does the users of the interface know which Ids to use?
s

sngrekov

02/21/2019, 9:57 PM
We put android resource ids directly into getString method, like resources.getString(R.string.blabla)
d

dewildte

02/21/2019, 10:13 PM
That's not what I mean
g

ghedeon

02/22/2019, 12:31 AM
yeah,
ResourseManager
is also good.. Similar situation with drawables. Sometimes you'd want to apply some color filter and there comes the context.
s

sngrekov

02/22/2019, 8:04 AM
@dewildte Oh, sorry, must have misunderstood your question. Can you please clarify what do you mean?
18 Views