Итак, моя проблема в том, что у меня есть сериализованный ArrayList, и я должен обновить его в своем графическом интерфейсе, чтобы динамически отображать его содержимое в ListView. Сериализация и десериализация отлично работают с использованием интерфейса DAO, но графический интерфейс не обновляет мой ListView.
Этот класс содержит мое взаимодействие с данными (в основном сохранение, загрузка...):
public class Medienverwaltung implements Serializable, IDAO{
private static final long serialVersionUID = 1L;
private List<Medium> medienliste;
public ObservableList<Medium> obList; //public for test-reasons
public Medienverwaltung(){
medienliste = new ArrayList<Medium>();
obList = FXCollections.observableArrayList(medienliste);
}
//[...]
public List<Medium> getMedienliste(){
return this.medienliste;
}
//[...]
}
Вот мой фрагмент реализации графического интерфейса:
public class HauptFenster extends Application{
private Medienverwaltung medienverwaltung;
@Override
public void start(Stage stage) throws Exception{
medienverwaltung = new Medienverwaltung();
VBox root = new VBox();
ListView<String> showliste = new ListView<String>();
MenuBar menuBar = createMenuBar(stage);
root.getChildren().add(menuBar);
root.getChildren().add(showliste);
//Make Listener and refresh the shown list!
medienverwaltung.obList.addListener(new ListChangeListener<Medium>(){
@Override
public void onChanged(ListChangeListener.Change<? extends Medium> change) {
showliste.getItems().clear();
for(Medium medium : medienverwaltung.obList){
//toString() is overwritten and works, too
showliste.getItems().add(medium.toString());
}
}
});
// this adds a Medium object to the Arraylist in Medienverwaltung
medienverwaltung.aufnehmen(new Bild("Foto12", 2017, "Zuhause"));
stage.setTitle("Medien Verwaltung");
stage.setScene(new Scene(root, 800, 400) );
stage.show();
}
//[...]
Я также устал менять весь ArrayList из класса «Medienverwaltung» на ObservableList, чтобы остался только один List, который работает для графического интерфейса, но не для сериализации и десериализации, как я догадался раньше. (и попробовал несколько других реализаций)
Кто-нибудь знает, как изменить мой код, чтобы он работал? И мой второй вопрос: как лучше всего использовать трехуровневую архитектуру?
Ниже приведена ссылка на Fabians Answer и ответ на мой комментарий к этому
Обновление №1.1 (дополнение для объяснения)
public interface IDAO {
// Save method
void speichern(List<Medium> liste) throws PersistenzException;
// Load method
List<Medium> laden() throws PersistenzException;
}
А вот и мой конкретный метод сохранения:
@Override
public void speichern(List<Medium> medienliste) throws PersistenzException{
File sfile = new File("medienliste.dat");
try(FileOutputStream fos = new FileOutputStream(sfile); ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(medienliste);
System.out.println("Serialisierung erfolgreich!");
}catch(IOException e){
e.printStackTrace();
System.out.println("Serialisierung fehlgeschlagen!");
}
}
Обновление №1.2 (дополнение для объяснения)
//[...] section of my GUI for saving
MenuItem speichern = new MenuItem("Speichern");
speichern.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent e){
try{
//Before: medienverwaltung.speichern(medienverwaltung.getMedienliste()); -> doesn't work because of serializing an ObservableList
medienverwaltung.speichern(medienverwaltung.getBackingList());
}catch(PersistenzException pe){
pe.printStackTrace();
}
}
});
//[...]
Но, как я предполагаю, это не лучший способ получить доступ к обратному списку таким образом.
Обновление №2:
чтобы строго соблюдать принцип инкапсуляции, я добавил перегруженный метод в класс Medienverwaltung:
public void speichern() throws PersistenzException{
speichern(backingList);
}
Так что теперь мой графический интерфейс вызывает только speichern(). Это фактически вызывает метод сохранения с помощью списка резервных копий, который более недоступен извне. Я надеюсь, что это не плохой стиль кодирования ^^
Кстати: Если вы читаете это и у вас похожая проблема, не используйте ObservableArrayList для синхронизации с обычным List, это не сработает! Вместо этого используйте ObservableList.