Waiting for the button to be pressed
How do I make the running method wait for the button to be clicked?
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);
}
});
}
2 answers
You can't do Thread.sleep(...)
in the UI thread, because if you block the UI thread, then, after a few seconds, you will get AN ANR (Application not responding) with a suggestion to force the application to stop. And in general, you can not load the UI stream.
In your task, you need to create a new thread in which your method will be executed and use thread synchronization (for example) on any object.
Here is the most primitive code that performs the task 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 clicked, a new thread is started, a corresponding message is output to the log, then the thread enters the synchronized block, the wait()
method is executed, and the thread falls asleep.
Next, when you click mSecondButton
, the UI thread enters the synchronized block (and it can enter because the thread launched by the mFirstButton
button after calling wait()
no longer owns the monitor) and calls notify()
, which leads to the resumption of the thread created by the button mFirstButton
.
UPD:
To execute the code in the main thread, you can use, for example, the runOnUiThread(...)
method:
runOnUiThread(new Runnable() {
@Override
public void run() {
// actions on UI-thread
}
});
boolean mark = false;
OnClickListener ocl = new OnClickListener() {
@Override
public void onClick() {
mark = true;
}
};
while(!mark) {
Thread.sleep(500);
}