skip to Main Content

Trying to follow good practice of not hardcoding strings in my app, I’m wondering if it is possible to access the string resources from a very simple class which stores strings :

class myData {
val myString = getString(R.string.name)
}

So far, I’m using :

import android.content.Context
import com.example.myAppName.R

class MyData(val context: Context) {
val myString = getString(R.string.name)
}

And then using it in :

val context = LocalContext.current
val myData = MyData(context)

But it seems a bit convoluted : there must be a cleaner solution for such a trivial usecase ?

2

Answers


  1. in non-android class you won’t have direct access to resources
    you can pass the Context to your class when you instantiate it

    import android.content.Context
    import com.example.myAppName.R
    
    class MyData(private val context: Context) {
        val myString = context.getString(R.string.name)
    }
    

    when you instantiate MyData, you can pass the Context directly:

        val context = LocalContext.current
    val myData = MyData(context)
    
    Login or Signup to reply.
  2. I am not sure why would you prefer this over default approach, but if you want it, there are two possible approaches that are similar to what you want.

    First approach:

        val Context.myString1
          get() = getString(R.string.my_string_1)
    
        val Context.myString2
          get() = getString(R.string.my_string_2)
    

    It uses extensions on context but it does not group strings in one class

    Second approach is similar and could be done like this:

    val Context.my_string_1
        get() = MyStrings.my_string_1(this)
    
    val Context.my_string_2
        get() = MyStrings.my_string_2(this)
    
    object MyStrings {
        fun my_string_1(context: Context) = context.getString(R.string.my_string_1)
        fun my_string_2(context: Context) = context.getString(R.string.my_string_2)
    }
    

    It will create similar thing to yours, but again, it will use extension on context.

    Looking at your code, I would strongly advice against capturing context like you are doing it as it can lead to leaks.
    The way you are doing it that MyData class is created on each recomposition.

    At the end, again, I think you should use existing composable:

    /**
     * Load a string resource.
     *
     * @param id the resource identifier
     * @return the string data associated with the resource
     */
    @Composable
    @ReadOnlyComposable
    fun stringResource(@StringRes id: Int): String {
        val resources = resources()
        return resources.getString(id)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search