Ожидание нажатия кнопки

796
25 декабря 2016, 19:37

Как сделать, чтобы запущенный метод ждал нажатие кнопки?

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);
        }
    });
}
Answer 1

Нельзя делать Thread.sleep(...) в UI-потоке, ибо если Вы заблокируете UI-поток, то, спустя несколько секунд, получите ANR (Application not responding) с предложением о принудительной остановке приложения. Да и вообще нельзя загружать UI-поток.

В Вашей задаче необходимо создать новый поток, в котором будет выполнятся Ваш метод и использовать синхронизацию потоков (например) на каком-либо объекте.

Вот самый примитивный код, который выполняет поставленную задачу:

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();
                }
            }
        });
    }
}

При нажатии кнопки mFirstButton запускается новый поток, в лог выводится соответствующее сообщение, далее поток входит в синхронизированный блок, выполняется метод wait() и поток засыпает.

Далее, при нажатии mSecondButton, UI-поток входит в синхронизированный блок (а войти он может потому, что запущенный по кнопке mFirstButton поток после вызова wait() уже не владеет монитором) и вызывает notify(), что влечет за собой возобновление работы потока, созданного по кнопке mFirstButton.

UPD:

Для того чтобы выполнить код в главном потоке, можно воспользоваться, например, методом runOnUiThread(...):

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // actions on UI-thread
    }
});
Answer 2
boolean mark = false;
OnClickListener ocl = new OnClickListener() {
    @Override
    public void onClick() {  
        mark = true;
    }
};
while(!mark) {
    Thread.sleep(500);
}
READ ALSO
Внедрение в контекстное меню android телефона

Внедрение в контекстное меню android телефона

Здравствуйте, подскажите пожалуйста есть ли возможность внедрить в меню "Копировать вставить" свой пункт? При нажатие на который мы бы переходили...

365
Некорректно работает поле oveflow:hidden

Некорректно работает поле oveflow:hidden

Поставил на блоки overlow:hidden и height:300pxПри наведении мышью на блок, он увеличивает высоту до 100%

355
Почему flexbox требует установки элемента в column?

Почему flexbox требует установки элемента в column?

Не могу разобраться, почему в шапке приходится выставлять элемент в column, а не в row, чтобы два новых блока в шапке располагались горизонтально

394