Посмотреть все другие ответы
Контекст предназначен для обмена данными, которые можно считать «глобальными» для дерева компонентов React, таких как текущий аутентифицированный пользователь, тема или предпочтительный язык. 1
blockquote>
Отказ от ответственности: это обновленный ответ, предыдущий использовал старый контекстный API
Он основан на принципе Consumer / Provide , Во-первых, создайте свой контекст
const { Provider, Consumer } = React.createContext(defaultValue);
Затем используйте через
{children} /* potential consumers */
и
{value => /* render something based on the context value */}
Все потребители, являющиеся потомками Провайдера будет повторно отображаться всякий раз, когда изменяется значение поддержки поставщика. Распространение от Провайдера к его Потребителям-потомкам не подлежит методу shouldComponentUpdate, поэтому потребитель обновляется даже тогда, когда компонент-предок освобождается от обновления. 1
blockquote>Полный пример, полу-псевдокод.
import React from 'react'; const { Provider, Consumer } = React.createContext({ color: 'white' }); class App extends React.Component { constructor(props) { super(props); this.state = { value: { color: 'black' }, }; } render() { return (
); } } class Toolbar extends React.Component { render() { return ( ); } }Consumer can be arbitrary levels deep
{value => The toolbar will be in color {value.color}
}
Проблема заключается в том, что вы пытаетесь закрыть Stage
из потока другого , чем JavaFX Application Thread. Посмотрев документацию по Stage
, вы увидите:
Объекты сцены должны быть сконструированы и изменены в приложении JavaFX Application Thread.
Тема приложения JavaFX создается как часть процесса запуска для среды исполнения JavaFX. Дополнительную информацию см. В классе Application и методе Platform.startup (Runnable).
Тем не менее,
Service
при запуске выполнит свойTask
на фоне . В частности, методcall()
дляTask
выполняется на указанном фоновом потоке. Я только что протестировал попытку закрытьStage
в фоновом потоке, чтобы узнать, что произойдет (независимо от того, будет ли выбрано исключение). Результатом былjava.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
.Причина, по которой вы этого не видите, - это не наблюдение за
Service
за сбой. Вы можете посмотреть ответ на этот вопрос , чтобы посмотреть, как смотреть на провал. Ответ конкретно говорит оTask
, но такое же поведение присутствует вService
.Что вам нужно сделать, чтобы заставить ваш код работать, чтобы убедиться, что
close()
вызывается в приложении JavaFX Нить. Самый простой способ сделать это - обернутьclose()
в вызовPlatform.runLater(Runnable)
.Service<Void> cicle = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } Platform.runLater(() -> close()); // wrapped in Platform#runLater return null; } }; } };
Вы также можете отменить
Service.succeeded()
, который всегда будет вызываться в потоке приложений JavaFX (но только в случае успехаService
). В этом случае вы удалите вызовclose()
из методаcall()
.Service<Void> cicle = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } return null; } }; } @Override protected void succeeded() { close(); } };
Существуют и другие способы: прослушивание свойства
state
с помощьюsetOnSucceeded(EventHandler)
, и т.д ...