Question

Im writing an application to read a line of text, highlighting each word successively as the line is read. The idea is to start playing the line (it's a picture book for kids, so one line at a time), then read the text, the length of each word in millisecs, then at the right time highlight the word in the textview.

My approach is: Put the words of the sentence into an array (and eventually the length of each work, but for the moment just assume 1000ms each); Write the word to a textViewPartial; delay length of word; Add next word to sentence and write it to textViewPartial....etc.

But I can't work out the timing. Read everything I can find on handler and async, and the best I can come up with is as follows - I put a postdelayed handler within a for loop. My brain says it will delay each time the loop is looper, but you can see from the logcat output that it doesn't. There is just one delay before the for loop starts. This is my first post and I can't see how you folks get your coloured code in from Eclipse, so I hope it looks ok.

   public class LineOutHanler extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_line_out_hanler);
    TextView t = new TextView(this);
    t=(TextView) findViewById (R.id.textView10);
    String textOut = "Oh how my spleen aches to see you again";
    final TextView textViewPartial = (TextView) findViewById(R.id.textView11);
    final String[] wordsOut = textOut.split(" ");
    final int wordsInSentence = wordsOut.length;
    int[] wordLength = new int[wordsInSentence];
            for (int counter=0;counter<=wordsInSentence-1;counter++){
            wordLength[counter]=wordsOut[counter].length();}
    String partialSentence ="";
    for (int counter=0; counter<=wordsInSentence-1; counter++){   
            String  c= addWordsOut(wordsOut[counter], partialSentence);
            textViewPartial.setText(c);
            partialSentence = c;
            Log.d("Word", partialSentence);
    final String partialOut=c;
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
      @Override
      public void run() {
                        textViewPartial.setText(partialOut);
            Log.d("Handler", partialOut);
        }
    } , 2000);}
    }
public String addWordsOut (String part, String upToHere)  {
upToHere=upToHere+" " + part;
return upToHere;
}
}

and the logcat output:

10-19 23:07:32.248: E/cutils-trace(39): Error opening trace file: No such file or directory (2)
10-19 23:07:32.368: D/AudioSink(39): bufferCount (4) is too small and increased to 12
10-19 23:07:32.379: D/Word(821):  Oh
10-19 23:07:32.379: D/Word(821):  Oh how
10-19 23:07:32.388: D/Word(821):  Oh how my
10-19 23:07:32.388: D/Word(821):  Oh how my spleen
10-19 23:07:32.388: D/Word(821):  Oh how my spleen aches
10-19 23:07:32.388: D/Word(821):  Oh how my spleen aches to
10-19 23:07:32.388: D/Word(821):  Oh how my spleen aches to see
10-19 23:07:32.398: D/Word(821):  Oh how my spleen aches to see you
10-19 23:07:32.398: D/Word(821):  Oh how my spleen aches to see you again
10-19 23:07:33.328: I/Choreographer(288): Skipped 30 frames!  The application may be doing too much work on its main thread.
10-19 23:07:33.368: I/ActivityManager(288): Displayed com.example.testtextout/.LineOutHanler: +1s820ms
10-19 23:07:35.320: W/AudioFlinger(39): write blocked for 1091 msecs, 1 delayed writes, thread 0x40e0b008
10-19 23:07:35.320: D/Handler(821):  Oh
10-19 23:07:35.329: D/Handler(821):  Oh how
10-19 23:07:35.329: D/Handler(821):  Oh how my
10-19 23:07:35.329: D/Handler(821):  Oh how my spleen
10-19 23:07:35.329: D/Handler(821):  Oh how my spleen aches
10-19 23:07:35.329: D/Handler(821):  Oh how my spleen aches to
10-19 23:07:35.339: D/Handler(821):  Oh how my spleen aches to see
10-19 23:07:35.339: D/Handler(821):  Oh how my spleen aches to see you
10-19 23:07:35.339: D/Handler(821):  Oh how my spleen aches to see you again
10-19 23:08:30.588: D/dalvikvm(396): GC_FOR_ALLOC freed 452K, 15% free 3047K/3556K, paused 40ms, total 65ms
10-19 23:25:42.149: D/dalvikvm(288): GC_FOR_ALLOC freed 850K, 31% free 5593K/7996K, paused 99ms, total 117ms

First question - is this the right approach in the first place? Second question - how can I get it to work?

Many thanks.

Was it helpful?

Solution

The problem is in your for loop. When you post the runnable, you always post in to run 2000ms in the future from the current point in time. When your code runs, it post these actions almost simultaneously. Thus you see your output occur 2 seconds later, happening at the same time. Instead, you could do what I do below, where I post it a multiple of 2000ms in the future, based upon which word you are working on.

for (int counter=0; counter<=wordsInSentence-1; counter++){   
        String  c= addWordsOut(wordsOut[counter], partialSentence);
        textViewPartial.setText(c);
        partialSentence = c;
        Log.d("Word", partialSentence);
        final String partialOut=c;
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                        textViewPartial.setText(partialOut);
                        Log.d("Handler", partialOut);
               }
        } , 2000*(counter+1));
}

As for your implementation, I'd recommend posting each new runnable as the previous one completes. Otherwise, you could create and post many runnables, eating into your memory usage unnecessarily, and making cleanup of the handlers a pain. For an initial POC, this isn't too bad and can be easily changed later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top