0

I'm creating a library (using Kotlin) and have a requirement to create a String extension that searches an ArrayList and returns a value. As the extension will be called many times I only want to load the ArrayList once and reuse it, so my approach so far is this:

Create the String extension, this is working, no issues.

The extension calls a function in a singleton which returns the results, this approach is working as I'm manually creating the ArrayList in the init of the singleton. The final solution needs to read a .csv file from the res/raw folder which will then create the ArrayList and this is where my problems start.

I'm struggling to find examples of reading a .csv file, currently I have a solution (test application, not a library) that reads the .csv from /app/src/main/assets using the following line of code:

       applicationContext.assets.open("test.csv").bufferedReader().use {}

Is this the best approach for reading a file, /res/raw seems more logical?

Assuming that my current approach is OK as soon as I move this code into my library and use it in the singleton I hit issues relating to context. I do not want the extension to have to pass context to the singleton, ideally I would like the init of the singleton to be able to fetch the context.

So in summary... I'm trying to find a way of my Singleton in a library to have access to the context so that the .csv file can be loading into an ArrayList once only.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Duncan Hill
  • 547
  • 2
  • 5
  • 16
  • See this post: https://stackoverflow.com/a/16053523/5125812 and this post: https://stackoverflow.com/a/9421473/5125812 -- Also be careful holding a reference to a context in singletons, make sure you are working with the application context. My suggestion would be to make your library as unaware of Android as possible, perhaps you load the required data elsewhere and then pass that into your library? – Victor Rendina Mar 28 '18 at 15:57

1 Answers1

0

From a library design standpoint I'd most probably keep the Context totally out of the equation and design my API in a way that it works with generic, existing interfaces.

For your given problem, what holds you back to simply design an API that requires an InputStream argument to read the CSV data and process them accordingly? The caller site can then either use that by context.resources.openRawResource(R.raw.csv_file), or context.assets.open("test.csv") or any other thing that gives you back an InputStream with the raw CSV contents.

As a plus, you are then able to easily test our new, fancy API by stuffing input data in with an ByteArrayInputStream that can easily be created. And finally, you have literally no Android dependency on your library, so your tests and production code runs on any JVM.

Thomas Keller
  • 5,933
  • 6
  • 48
  • 80