Question

My program should repeat a method until a button is pressed. I tried this, but is doesn't work:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tts = new TextToSpeech(this, this);
    Button button1 = (Button)findViewById(R.id.button1);
    Button button2 = (Button)findViewById(R.id.button2);
    button1.setOnClickListener(this);
    button2.setOnClickListener(this);
}


public void onClick (View v){
    switch(v.getId()) {
    case R.id.button1: 
        mainprogram();
        break;
    case R.id.button2: 
        perform = false;
        break;
    }
}



public void mainprogram(){

    while(perform == true){
        speak();
        }
    }

(Of course I programmed the "speak()" method)

Could you tell me where the problem is or if there are any methods to solve it?

Was it helpful?

Solution 2

I think the problem is that you are running the while loop in the same thread your listeners and your UI is running in. Thus, as soon as your program enters mainprogram(), it will hang up in this loop, because it can no longer react to your UI (thus, perform will always be true)!

The problem you are facing might be solved with running the content of mainprogram() in another Thread.

Your code might look something like this:

class MainActivity extends Activity
{
    //...
    private static boolean perform;

    private static getPerform()
    {
        return perform;
    }

    public void onClick (View v){
        switch(v.getId()) {
            case R.id.button1:
                perform = true;

                Thread t = new SpeakThread();
                t.start();

                break;

            case R.id.button2:
                perform = false;
                break;
        }
    }
}

class SpeakThread extends Thread
{
    public void run()
    {
        while(MainActivity.getPerform())
        {
            speak();
        }
    }
}

OTHER TIPS

The problem is that your loop runs on the UI thread. I guess the whole UI freezes as you start the loop.

You should run it on a separate thread. Like:

case R.id.button1: 
    Thread th = new Thread(new Runnable(){
       public void run(){
           mainprogram()
       }
    }).start();
    break;

Also, since you modify "perform" from separate threads, you should also make the perform variable volatile, to make the changes visible to other threads, as soon as the modification happens.

You can read more about volatile here: Do you ever use the volatile keyword in Java?

Since mainprogram will be running on the UI thread, it will block all UI until it breaks from the loop.

Clicking R.id.button2 will not respond (because the UI thread is blocked), so perform will not be set to false.

Perform mainprogram off the main thread, and clicking the button will stop it at some point later

To stop a while loop just use break;

So in your case:

while(perform == true){
    speak();
    if( ... somereason ...) break;
}

Where ... somereason ... should be valid code.

If the method speak() is the one that decides if you need to break, just put the code of speak() directly in the while loop instead of the method call. Or return false from speak and check:if(!speak()) break;

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