0

I am making an android app. There is an activity in the app, which when triggered, makes a sparsearray and fills it with data. Now this process takes upto 1 minute on the emulator, which is very long. So I want to make that sparsearray once, right when the app is launched, and save the sparsearray in RAM for the lifetime of the app. And whenever the activity is triggered it should access the sparsearray in RAM instead of making a new one, thus saving time and processing power. Can this be done, if so how? Sorry if this question is dumb, I am new to android. Thanks! *Edit: This is what the sparsearray making function looks like: //function which accesses sparsearray making function

public String[] process(){
InputStream is = context.getAssets().open("feedtitlesandaddresses.txt");
        InputStreamReader iz=new InputStreamReader(is);
        BufferedReader br = new BufferedReader(iz);
        String line = null;
while((line=br.readLine())!=null) {

            readLine(line);

            }}
//sparsearray making function
private void readLine(String line) {
//some string processing(omitted here)
int num1 = Integer.parseInt(firstNumber);

        //int num2 = Integer.parseInt(secondNumber);
        if(sparseArray.get(num1) == null) {

            sparseArray.put(num1, new SparseArray<String>());

        }
        temporarySparseArray = sparseArray.get(num1);

        for(int w=0;w<size;w++){
        temporarySparseArray.put(w, array1[w]);
                }
        sparseArray.put(num1, temporarySparseArray);

        temporarySparseArray = null;
}
Tom Wong
  • 31
  • 1
  • 1
  • 4
  • Could you provide some code please? And if your AVD has only some MHz it will be slow. – r0- Mar 20 '13 at 06:51
  • @staaar How can I find out how many MHz my AVD has? – class stacker Mar 20 '13 at 06:52
  • @staaar Which part of the code? – Tom Wong Mar 20 '13 at 06:53
  • @TomWong Start a Thread or maybe AsyncTask in `onCreate()` of your `Application` object and save the results there. – class stacker Mar 20 '13 at 06:53
  • Use your Code in an AsyncTask, that put's the ressource intensive part in the background. – r0- Mar 20 '13 at 07:04
  • The reasons why I would consider a Thread in favour of an AsyncTask: 1) It's not a typical case where one needs to re-sync with the UI in a complex way. 2) Other AsyncTasks could not run at the same time on current Android versions unless the Exedcutor is chosen. 3) AsyncTasks are intended only for short operations; a task which takes a minute can also take a long time on a real device. So please do yourself a favour and consider a Thread. Also, start it from your Application subclass, and store the result there. – class stacker Mar 20 '13 at 07:22
  • @TomWong I must say I should have insisted on looking at your code first, which you now published [over here](http://stackoverflow.com/q/15521996/1856738). But regardless of the discussion there, I presume you read _a lot of data_, despite your somewhat inefficient handling, so I presume you'll want to read it in asynchronously, regardless of how good you can optimize your code. But it would of course be enlightening to learn how many lines (records) you read in. – class stacker Mar 20 '13 at 12:11
  • @ClassStacker Thanks for the answer. I read in 3200 lines, ie. 3200 iterations.... – Tom Wong Mar 20 '13 at 13:13
  • @TomWong I think with 3200 lines, you want to read the file asynchronously either way, regardless of whether it takes two seconds or a minute, because if you don't, then the user interface will not respond (later you may even consider to have an animation, which would not work if you block the main thread reading your data). – class stacker Mar 20 '13 at 14:20
  • @ClassStacker So should I use the separate thread method or the async method..? – Tom Wong Mar 20 '13 at 14:59
  • @TomWong If you read the AsyncTask reference, you'll find that it says it's intended for tasks which takes a few seconds _at most_. Also, its design with `onPostExecute()` etc is clearly for feeding data back into the user interface. I stick to my suggestion to use a Thread. – class stacker Mar 20 '13 at 15:25

2 Answers2

0

You can write you object in the android internal or external file system, and you can read the object when you want to use it.

  • Which ways of reading and writing the object to/from the file system would you suggest, and how will their performance be depending on the size of the object? WHat will the implications be if the original data changes? – class stacker Mar 20 '13 at 07:26
0

I feel this question deserves an answer, and I was sure someone would come up with one, but, hmm, not really so far; and if I were Tom Wong, it would currently look to me as if StackOverflow was a place where wannabe experts start fighting over questions rather than answering them. ;) So here we go.

  • Do something at startup, the result of which lasts as long as your App is in memory: The right place to do this is Application.onCreate(), for which you need to subclass Application. It is okay to store the result in the Application object as well in this case, where you can access it from any Activity by getting the Application context.

  • Do something that will take some time: In general, it's a good idea to use AsyncTask on Android, but it is specialized for doing things which relate to the User Interface but must not block it. Also, without some explicit tuning, its behaviour will vary amongst different Android versions. Currently, without further measures, if you did your computation via AsyncTask, other AsyncTasks would have to wait first. Also, what you want to do is not a classic task for using an AsyncTask, so use a one-time Thread which simply stores its result finally in a volatile reference.

The following code snippet should give you the idea.

final class MyApplication extends Application {
    public volatile String[] expensiveToCompute;
    @Override
    public void onCreate() {
        expensiveToCreate = null;
        (new Thread() {
            @Override
            public void run() {
                String[] result = computeMyData();
                // it is important to assign the locally created data at once here
                expensiveToCompute = result;
            }
        }).start();
    }
}

In this way, expensiveToCompute will be null until the asynchronous computation has finished.

It is important to understand that this Thread will run until it has finished, and that it holds a reference to your MyApplication object. This means that even if the user leaves your app, your Thread will still continue if it has not finished until then.

This is in fact nice, because either Android decides to leave your Application object alive just because it can, in which case the user experience improves. Or Android kills the whole process with the Application object, your Thread and any held data, in which case it will start from scratch next time.

One more thing about, umm, suggestions to move expensive computations into AsyncTask etc: Android assigns a default background priority to such threads, and all background threads will (currently) have to live with 10% CPU time altogether no matter whether the Android system is idle otherwise. So many people who move intensive computations to background tasks notice that it will take ten times longer. Hence, you may want to read my suggestions regarding how to handle this here and/or here.

Community
  • 1
  • 1
class stacker
  • 5,357
  • 2
  • 32
  • 65