2016-08-03 9 views
1

Следующий код производит IllegalStateException - не на приложении FX Thread -.Gluon Connect DataProvider.retrieveList результаты в IllegalStateException

private void populateListView(){ 
    GluonObservableList<MyClass> items = DataProvider.retrieveList(restClient.createListDataReader(MyClass.class)); 
    listview.setItems(items); 
} 

Я предполагаю, что причина этого заключается в том, что код, который добавляет элементы из Iterator к GluonObservableList не обернута в Platform.runLater(), несмотря на другие вызовы в retrieveList()?

ответ

1

Обновление элемента пользовательского интерфейса (такого как listview) должно выполняться из потока прикладных программ FX. Если popultListView() вызывается из фонового потока, updateableList обновляется в фоновом режиме, заставляя listview пытаться обновить его из фона.

Установка наблюдаемого списка в listview с использованием Platform.runLater происходит в потоке FX, но наблюдаемый список все еще обновляется в фоновом режиме после его загрузки в список.

new Thread(()->{ 
    GluonObservableList<MyClass> items = DataProvider.retrieveList(restClient.createListDataReader(MyClass.class)); 
    //Option 1 
    //listview.setItems(items); 
    //Option 2 
    //Platform.runLater(()->listview.setItems(items)); 
    //Option 3 
    //items.initializedProperty().addListener((obv,ov,nv)->{ 
    // listview.setItems(items); 
    //}); 
    //Option 4 
    items.stateProperty().addListener((obvs,ovs,nvs)->{ 
     if (nvs.equals(ConnectState.SUCCEEDED)) { 
      listview.setItems(items); 
     }else if(nvs.equals(ConnectState.FAILED)){ 
      MobileApplication.getInstance().showMessage("Rest API request failed"); 
     } 
    }); 
}).start(); 


Вариант 1 Вариант 2 и обновляют ListView, прежде чем данные загружаются в observableList. Варианты 1 и 2 вызывают множественные исключения (и вариант 1 просто уродлив).

Оба варианта 3 и вариант 4 запускают обновление списка после загрузки наблюдаемого списка и обрабатываются в потоке приложения FX.
В качестве альтернативы вы можете обернуть любой вызов populateListView() в Platform.runLater

+0

Я предполагаю, что мой вопрос должен быть более точным ... На самом деле я использую вариант 3, который, я думаю, является способом, которым «GluonObservableList» является предполагается использовать. Я просто задавался вопросом, почему 'Iterator' в' DataProvider.retrieveList' не завернут в 'Platform.runLater()', что теперь имеет для меня прекрасный смысл, например. когда вы рассматриваете ситуацию, когда вы используете его в «Thread», который не обновляет пользовательский интерфейс. – jns

+0

Просто добавив быстрый комментарий к этому, имеет смысл непосредственно установить элементы в ListView, как в Варианте 1. Поскольку GluonObservableList является ObservableList, любые элементы, которые добавлены к нему, будут автоматически отображаться в ListView так же, как при использовании обычного ObservableList. Вызов DataProvider.retrieveList также должен выполняться в потоке приложения FX. Gluon Connect уже выполняет фактическое извлечение списка в своем собственном фоновом потоке, поэтому разработчик не имеет причины вызывать это из-за потока приложений FX. –

+0

В этом примере я специально назвал DataProvider и заполнил список из фонового потока для опции 1., из-за которой возникла ошибка .. Это будет работать, если в потоке FX. Вариант 2 все еще вызывает ошибки, поскольку DataProvider все еще вызывается из фона. DataProvider отлично справляется с тем, что нет необходимости обращаться к фоновому потоку для запроса данных. – AhaMoment