How to make the running method wait for a button click?

yesButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { status = 1; synchronized (sMonitor) { sMonitor.notify(); } } }); noButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { status = 2; synchronized (sMonitor) { sMonitor.notify(); } } }); ... private void askQuestion1() { new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "Start"); jokeTextView.setText(R.string.joke_1_1); synchronized (sMonitor) { try { sMonitor.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (status == 1) { askQuestion2(); } if (status == 2) { askQuestion6(); } } }).start(); } 

....

 private void askQuestion2() { runOnUiThread(new Runnable() { @Override public void run() { jokeTextView.setText(R.string.joke_1_2); } }); } 
  • Something in the style of while (!isClicked) { Thread.sleep(1000); } while (!isClicked) { Thread.sleep(1000); } setting the isClicked value to true in the keystroke handling method? - Regent
  • Show the existing code. - post_zeew
  • @MaximFomichev correctly do I understand that if there are 100 questions, then you will create 100 askQuestionXX methods? - Regent
  • there will not be 100 questions, the method is needed to return to previous methods based on the chosen answer - Maxim Fomichev

2 answers 2

You can not do Thread.sleep(...) in the UI-stream, because if you block the UI-stream, then after a few seconds, get ANR ( Application not responding ) with a proposal to force the application to stop. And generally it is impossible to load a UI stream.

In your task, you need to create a new stream in which your method will be executed and use synchronization of threads (for example) on any object.

Here is the most primitive code that performs the task:

 public class MainActivity extends AppCompatActivity { private Button mFirstButton; private Button mSecondButton; private static final Object sMonitor = new Object(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFirstButton = (Button) findViewById(R.id.first_button); mSecondButton = (Button) findViewById(R.id.second_button); mFirstButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { Log.d("TAG", "Start"); synchronized (sMonitor) { try { sMonitor.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } Log.d("TAG", "End"); } }).start(); } }); mSecondButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { synchronized (sMonitor) { sMonitor.notify(); } } }); } } 

When the mFirstButton button is mFirstButton , a new stream is launched, a corresponding message is output to the log, then the stream enters the synchronized block, the wait() method is executed and the stream falls asleep.

Further, when mSecondButton , the UI stream enters the synchronized block (it can enter because the thread started by the mFirstButton button after calling wait() no longer owns the monitor) and causes notify() , which entails resuming the flow, created by the mFirstButton button.

UPD :

In order to execute code in the main thread, you can use, for example, the runOnUiThread(...) method:

 runOnUiThread(new Runnable() { @Override public void run() { // actions on UI-thread } }); 
  • thanks, I will understand - Maxim Fomichev
  • And how can I return to the main stream to change the activity? - Maxim Fomichev
  • @ MaksimFomichev, Added in response. - post_zeew
  • I tried it but ide doesn't skip, updated the code in question - Maxim Fomichev
  • @MaximFomichev, In the code that is in question, do not call the runOnUiThread(...) method runOnUiThread(...) . - post_zeew
 boolean mark = false; OnClickListener ocl = new OnClickListener() { @Override public void onClick() { mark = true; } }; while(!mark) { Thread.sleep(500); } 
  • Thanks, I get a white screen, remove the while loop, everything works, here is my method private void askQuestion1() { jokeTextView.setText(R.string.joke_1_1); while (!isClicked) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } if (status == 1) { askQuestion2(); } if (status == 2) { askQuestion6(); } } private void askQuestion1() { jokeTextView.setText(R.string.joke_1_1); while (!isClicked) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } if (status == 1) { askQuestion2(); } if (status == 2) { askQuestion6(); } } private void askQuestion1() { jokeTextView.setText(R.string.joke_1_1); while (!isClicked) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } if (status == 1) { askQuestion2(); } if (status == 2) { askQuestion6(); } } - Maxim Fomichev
  • @MaksimFomichev, Thread.sleep(...); cannot be done in a UI thread. - post_zeew