I am just fighting to get some file resource loade...
# multiplatform
m
I am just fighting to get some file resource loaded into my app via moko-resources. I am wondering how I am supposed to access a file resource from common code if the FileResource method to get at the text of this file has a signature like this on desktop
Copy code
fun readText(): String
but
Copy code
fun readText(context: Context): String
on Android. On any other platform than Android there is no Context. Am I supposed to somehow wrap that again in some expect/actual code of my own, or what? I just don’t get it.
j
The real problem is where you are trying to get the final String value. You shouldn't get a String outside of the view IMO, instead you should use the common reference.
As it depends on the context, you can get problems getting it outside the view as it was shared long time ago about getting resources inside a
ViewModel
. https://medium.com/androiddevelopers/locale-changes-and-the-androidviewmodel-antipattern-84eb677660d9
If the UI framework is shared, for example using Compose, it should be easy to access to the resource in common as you can have an implementation in Android using
LocalContext
. But it would be accessing in the view too
m
Thanks, but I am not using any Android ViewModel and FileResource.readText is assumed to return the unmodified content of a file packaged with the application and interpreted as a String. (Actually I’d prefer to just get the content as a ByteArray but there is currently no code for that.) The raw content of this file should not be influenced by any of Androids various config changes as far as I understand it. So my question was only whether I am missing any API to access this file in a platform independent way or not.
j
Without dependency injection and/or a content-provider I don't think you can
You can have a global nullable
Context
in a singleton and with that initializer change it to the context provided, so you can access it in your actual without passing it as parameter
Copy code
var globalContext: Context? = null

class FileInitializer: Initializer<Context> {
    override fun create(context: Context): FileInitializer {
        globalContext = context
        return ...
    }

    override fun dependencies(): List<Class<out Initializer<*>>> = ...
}
k
What I usually do is introduce a class in common:
Copy code
expect class TextReader {
  fun readText(): String
}
then have a platform specific class that might have platform specific fields Android:
Copy code
actual class TextReader(private val context: Context) {
  fun readText(): String {
    return context.getString(...)
  }
}
and iOS
Copy code
actual class TextReader {
  fun readText(): String {
  // iOS implementation goes here
  }
}
Similar concept is described in docs here