這裏的基本思路是使用單個數據模型,它在需要訪問共享數據的組件之間共享。在afterburner.fx中使用@Inject
將爲您提供一種便捷的管理方法。
對於設計模式,首先要注意的是,afterburner.fx(也可能是一般的FXML-「controller」機制)實際上是基於MVP模式(而不是MVVM模式) 。 FXML文件表示(被動)視圖;主講人當然是主持人,模型是根據應用需求來實現的。
通常,您使用的框架是決定使用哪種模式的重要部分,所以我認爲我的主要建議是在這裏使用MVP模式。使用MVP,這看起來像下面這樣:
您可以在模型中創建一個ObservableList
:在主持人的具有ListView
認爲
public class Model {
private final ObservableList<String> itemList = FXCollections.observableArrayList();
public ObservableList<String> getItemList() {
return itemList ;
}
}
然後執行:
public class ListPresenter {
@Inject
private Model model ;
@FXML
private ListView<String> listView ;
@FXML
public void initialize() {
listView.setItems(model.getItemList());
}
}
以便ListView
在模型中使用ObservableList
作爲其後備列表項目。這意味着如果該列表更改,則ListView
將自動更新。
在主持人對於具有文本字段中的視圖,你這樣做:按下按鈕現在
public class AddItemPresenter {
@Inject
private Model model ;
@FXML
private TextField textField ;
// handler for button press:
@FXML
private void handleButton() {
model.getItemList().add(textField.getText());
}
}
時,在文本字段添加到模型的項目列表。因爲您將該列表設置爲列表視圖的支持列表,所以文本顯示在列表視圖中。
如果你想在這裏強制MVVM模式,我認爲你必須考慮MVVM「查看」爲包括從加力FXML,主持人對。所以你最終得到的是一個看起來像M(VP)VM模式的東西。我不像MVC和MVP那樣熟悉MVVM,但據我所知,它有三個組件:熟悉的數據模型(M),視圖(V)和視圖模型(VM)。視圖模型的作用是表示視圖的狀態,包括動作,但它對實際視圖本身一無所知。在上面的例子中,你會有兩個視圖模型;每個觀點一個。請注意,數據模型(M)仍然存在,當然視圖模型將需要訪問它。他們需要共享相同的數據模型實例,以便他們可以訪問和操作相同的數據。
我覺得這樣的一個實現看起來像
public class ListViewModel {
@Inject
private Model model ;
private final StringProperty selectedItem = new SimpleStringProperty();
public ObservableList<String> getItems() {
return model.getItemList();
}
public StringProperty selectedItemProperty() {
return selectedItem ;
}
public String getSelectedItem() {
return selectedItemProperty().get();
}
public void setSelectedItem(String item) {
selectedItemProperty().set(item);
}
}
的Model
類是和以前一樣。主持人(視圖MVVM)的工作是到視圖綁定到視圖模型:
public class ListViewPresenter {
@Inject
private ListViewModel viewModel ;
@FXML
private ListView<String> listView ;
@FXML
public void initialize() {
listView.setItems(viewModel.getItems());
viewModel.selectedItemProperty().bind(listView.getSelectionModel().selectedItemProperty());
}
}
同樣爲「添加項目」模塊視圖模型看起來像
public class AddItemViewModel {
@Inject
private Model model ;
private final StringProperty currentItem = new SimpleStringProperty();
private final Runnable addItemAction = this::addItem ;
public StringProperty currentItemProperty() {
return currentItem ;
}
public String getCurrentItem() {
return currentItemProperty().get();
}
public void setCurrentItem(String item) {
currentItemProperty().set(item);
}
public Runnable getAddItemAction() {
return addItemAction ;
}
private void addItem() {
model.getItemList().add(getCurrentItem());
setCurrentItem("");
}
}
和AddItemPresenter
現在看起來像
public class AddItemPresenter {
@Inject
private AddItemViewModel viewModel ;
@FXML
private TextField textField ;
@FXML
private Button addButton ;
@FXML
public void initialize() {
viewModel.currentItemProperty().bindBidirectional(textField.textProperty());
addButton.setOnAction(e -> viewModel.getAddItemAction().run());
}
}
這裏的效果實際上只是在視圖和(數據)模型之間插入一個附加層。實際效果就好像主持人現在沒有真正「拉開重量」,這通常表明應用程序設計過度,層數過多。但是,您確實獲得了優勢,因爲視圖模型現在比演示者更「測試友好」(當然,通過爲注入的模型提供setter或構造函數參數可以使其更加有效)。
感謝您的回答,但我將演示者解釋爲Model-View-ViewModel原理中的視圖。所以他們沒有任何查看邏輯。 它們只將視圖元素(如ListView)與ViewModel連接起來。 在示例中,Presenter具有邏輯 listView.setItems(model.getItemList()); model.getItemList()。add(textField.getText()); 並且這不是真的測試友好(因爲@Inject和@FXML)。 在我看來,視圖模型必須處理這種交流。 這是一個錯誤的審議? THX – user2558928
@ user2558928 afterburner.fx使用的底層模式是MVP(被動視圖)模式(如果使用FXML和「控制器」類,這也是非常正確的)。在這之上強制設計一個MVVM設計將會非常棘手 - 您最終會得到某種M(VP)VM設計。也許你可以在你的問題中添加一些代碼來顯示你從哪裏開始? –
@ user2558928查看MVVM方法的更新(我認爲...)。 –