tags:

views:

227

answers:

4

I am making an app for Android, in my Activity I need to load an array of about 10000 strings. Loading it from database was slow, so I decided to put it directly into one .java file (as a private field). I have about 20 of these classes containing string arrays and my question is, are all the classes loaded into memory after my application is started? If so the Activity in which I need these strings would be loaded quickly, but the application as a whole would have a slow start... Is there other way, how to very quickly load an 10000 string array from a file?

UPDATE: Why I need these strings? My Android app allows you to find "journeys" in Prague's public transit - you choose departure stop, arrival stop and it finds your journey (have a look here). My app has a suggestions feature - you enter leter "c" as your departure stop and a suggestions ListView appears with stops starting with "c". For these suggestions I need the strings. Fetching the suggestions from database is slow (about 400ms on G1).

+3  A: 

A class is loaded only when it is first referenced.

Though you need an array of 10000, you may not need all at once. Here is where the concept of paging comes in. Paging is often done in Android.Initialy have only a small amount of array in memory, and as you need it, keep loading it in to memory and unloading any previous data from memory if not wanted.

For e.g. in any table, at one shot, the user may see at best 50 records, then he will have to scroll(considering his screen is not size of an iMax movie theatre). When he scrolls, load the next chunk of data and unload any data that is now inivsible to the user.

Suraj Chandran
Unfortunately I need all 10000 (see updated question). So if I have the class name somewhere in my Activity code, JVM would load the class when my Activity is started?
fhucho
@fhucho - yes it would.
Stephen C
Not sure about android but the sun JVM does lazy loading. The class will be initialized when it is first USED. e.g the first time some code actually uses a static value from the class or calls new on it. Just importing it does nothing and if NEW or MyClass.staticMethod() is not called in your execution path then it's never loaded.
Chris Nava
I'm fairly sure the Android runtime does that, too.
Matthias
+1  A: 

When is a Type Loaded? This is a surprisingly tricky question to answer. This is due in large part to the significant flexibility afforded, by the JVM spec, to JVM implementations. Loading must be performed before linking and linking must be performed before initialization. The VM spec does stipulate the timing of initialization. It strictly requires that a type be initialized on its first active use (see Appendix A for a list of what constitutes an "active use"). This means that loading (and linking) of a type MUST be performed at or before that type's first active use.

From http://www.developer.com/java/other/article.php/2248831/Java-Class-Loading-The-Basics.htm

Bruno Rothgiesser
A: 

I don't think that you will be happy with maintaining 10K Strings, hardcoded at Java files.

Rather check if you are using the right database for your problem and if your indices are set correctly. A wrong index can cause really poor performance.

Additionally you should limit the amount of results returned by the query, but make sure you don't fetch the entries one by one.

If nothing fits, you can still preload the Strings from the database at startup.

You could preload, let's say 10 entries, for each character. If a character is keyed in, you can preload the entries with that character following another and so on.

Hardcoded
+3  A: 

First, 400ms to perform a simple database query is really slow. So slow that I'd suspect that there is some problem in your database schema (e.g. indices) or your database connection configuration.

But if you a serious about not using a database, there are a couple of alternatives to what you are currently doing:

  1. Arrange that the classes containing the arrays are lazily loaded as required, using Class.forName(...). If you implement it right, it should be possible for the garbage collector to reclaim the classes after they have been loaded and the strings have been added to your primary data structure.

  2. Turn the 10000 Strings into a flat file, put the file into your app's JAR file. Then use Class.getResourceAsStream(...) to open the file and read it into the in-memory array.

  3. As above, but using an indexed file and replacing the array with a data structure that allows you to read Strings from the file lazily. (This will be a bit complicated, but if you are worried by the memory consumed by the 10000 Strings, this will help address that.)

Stephen C
Thanks, now I am using Class.forName("") and it's very fast.
fhucho