簡體   English   中英

如何在CellWT的GWT中正確實現MVP?

[英]How to properly implement MVP in GWT for a CellTree?

想象一下,我有一個CellTreeWidget類,其中包含一個CellTree

我想寫一個演講者,與

  1. CellTreeWidget實例和
  2. 用於獲取數據的遠程服務。

CellTreeWidget顯示的數據是項目列表。 每個項目都有一個父項目,並且屬於一個容器。

public class Container
{
    public List<Item> getItemList();
    public void setItemList(List<Item> aItemList);
}

public class Item
{
    public int getItemId();
    public int getParentItemId();
}

演示者涉及以下過程:

  1. 用戶選擇一個容器(請參閱下面的Presenter.startEdit )。
  2. 用戶保存對容器所做的更改(請參見下面的Presenter.save )。

當用戶選擇一個容器時,必須更新CellTreeWidget以顯示新選擇的容器的項目。

當用戶保存對容器所做的更改時,演示者必須

  1. 向遠程服務發送保存請求,並
  2. 如果請求已正確處理,請確保樹中的項目已更新。

步驟2是必需的,因為用戶能夠在客戶端上創建新項目。 當它們保存在服務器上時,它們的數據(主鍵)將被更改。

為了實現這一點,有人告訴我使用以下方法:

public class Presenter
{
    private RemoteService service;
    private View view;
    private ListDataProvider<Item> dataProvider;
    private Container data;

    public Presenter()
    {
        dataProvider = new ListDataProvider<Item>(new ItemProvidesKey());
    }
    public void setService(final RemoteService aService) 
    {
        service = aService;
    }
    public void setView(final View aView) 
    {
        view = aView;

        final HasData<Item> dataToDisplay = view.getDisplay();

        if (dataToDisplay != null)
        {
          dataProvider.addDataDisplay(dataToDisplay);
        }
    }
    public void save() {
        List<Item> allPages = new ArrayList<Item>();
        allPages.addAll(dataProvider.getList());
        data.setItemList(allPages);

        service.save(data, new AsyncCallback<ContainerSaveResult>() {
            @Override
            public void onSuccess(ContainerSaveResult result) {
                afterSave(result);
            }

            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Save error: " + caught.getMessage());
            }
        });
    }

    protected void afterSave(ContainerSaveResult result) 
    {
        for (final Page curItem : dataProvider.getList()) 
        {
            final Integer oldId = curPage.getItemId();
            final Integer newId = result.getNewItemIdsByOldItemIds().get(oldId);

            if (newId != null) 
            {
                curPage.setItemId(newId);
            }
        }

        dataProvider.flush();
    }
    public void startEdit(Container aContainer) 
    {
        data = aContainer;
        if (data != null) 
        {
            view.getDisplay().setRowCount(data.getItemList().size(), true);
            dataProvider.setList(data.getItemList());
        }
    }
}

CellTreeWidget實現View接口,其定義如下:

public interface View extends IsWidget, HasSelectionChangedHandlers {
  HasData<Item> getDisplay();
}

這種方法的問題在於,我看不到任何明顯的方法在CellTreeWidget類中提供方法HasData<Item> getDisplay()CellTreeWidget

因此,我的問題是:如果你

  1. 具有樹狀結構
  2. 顯示在CellTree
  3. 可以在客戶端(用戶添加新項目)和
  4. 在服務器上(新項目保存在數據庫中並獲得新的ID)

並希望實現一種干凈的機制來更新數據和視圖,如何以正確的GWT方式進行?

免責聲明

不幸的是, CellTree是一個非常復雜的小部件,與CellTableDataGrid相比,它使用完全不同的概念。
這也是為什么它不像其他CellWidgets那樣阻礙HasData接口的原因。

此外,通過CellTree更新和刷新其節點並沒有得到足夠好的現成支持。 有幾種解決方法(請參閱此處此處 )。 CellTree擴展也試圖解決其中的一些問題( ProjectCodeDemo )。

我建議先用CellTree實現用例,然后再擔心它是否適合MVP風格。 我已經告訴你,在處理CellTree時,在ViewPresenter之間繪制清晰的界限並不容易。

您的用例

如果我正確理解了您的用例,那么您將擁有一個Container對象列表(您正在使用CellList嗎?),並且當您選擇一個特定的容器時,您想要顯示CellTree中的項目列表並允許用戶編輯和添加/刪除項目。

我將嘗試強調重要步驟:

1.)您的數據結構與CellTree不能很好地配合使用。 您應該引用每個項目的父項和子項列表:

public class Item
{
    public int getItemId();
    public Item getParent();
    public List<Item> getChilds();
}

CellTreeDataGridCellTree不同, CellTable使用TreeViewModel

2.)定義一個自定義TreeViewModel

public class MyCustomTreeModel implements TreeViewModel {

    private final SelectionModel<Item> selectionModel;
    private final ValueUpdater<Item> valueUpdater;

    public MyCustomTreeModel(final SelectionModel<Item> selectionModel, ValueUpdater<Item> valueUpdater) {
        this.selectionModel = selectionModel;
        this.valueUpdater = valueUpdater;
    }

    @Override
    public <T> NodeInfo<?> getNodeInfo(final T value) {
        // The root node is the container
        ListDataProvider<Item> = new ListDataProvider<Item>();
        if (value instanceof Container) {
            provider.setList(((Container)value).getItemList();
            return new DefaultNodeInfo<Item>(provider, containerCell, selectionModel,null);
        }
        provider.setList(((Item)value).getChilds());
        return new DefaultNodeInfo<Item>(provider, itemCell, selectionModel, valueUpdater);
    }

    @Override
    public boolean isLeaf(Object value) {
        Item item = (Item) value;
        return value != null && item.getChild().size() == 0;
    }
}

3.)在View實例化自定義MyCustomTreeModel並使用選定的Container實例創建CellTree (選擇Container ,可以從Presenter中進行創建:

public void onStartEdit(Container container, SelectionModel<Item> selectionModel, ValueUpdater<Item> valueUpdater) {
    CellTree tee = new CellTree(new MyCustomTreeModel(selectionModel,valueUpdater));
}

摘要

同樣,您可能會遇到刷新問題,並且必須在TreeViewModel中添加add()remove()函數以添加和刪除項目。

查看鏈接的問題以獲取一些解決方法和代碼,我建議使用擴展的CellTree 如果可能,請使用其他小部件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM