2011-09-28 50 views
2

我已經開始了一個GWT項目,我決定試試UiBinder。我很難在UiBinder之上鋪設MVP模式。GWT MVP UiBinder - 將參數傳遞給主持人

當我使用GWT-pure-java時:我會使用杜松子酒爲我的演示者注入相應的視圖。這非常簡單,如果我想將ID傳遞給主持人,那麼我只需將ID傳遞給主持人的構造函數即可。

與UiBinder並不那麼直接。我幾乎可以肯定,我錯過了一些東西,因爲很多人都聲稱UiBinder和MVP是天作之合......所以我希望在這個查詢中得到一些堅實的迴應;-)

我在一些微不足道的GWT-UiBinder的例子看到的,是該視圖是由粘結劑創建,那麼:

  1. 視圖構建主持人無論是在它的構造函數或通過@UIFactory方法。
  2. 將相應的演示者傳遞給視圖(通過setter,在構建視圖之後不用說)。

第一種方法是,如果主持人在視圖中構建,如何將ID傳遞給主持人?你會做view.getPresenter().setId(42);,然後主持人會去服務器獲取一些信息,並要求視圖顯示...味道不好。

在第二種方法中,最終會出現一個非直觀的對象圖,其中不清楚誰是消費者,誰是生產者。此外,在情況下認爲需要從主持人(幾乎所有的用例需要這個)你會做一個信息:提前

//some code would create the presenter pass it the id and then call view.setPresenter 
class MyView { 
    void setPresenter(MyPresenter p) { 
    this.presenter = p; 
    //OK now that i have my presenter how do I ask it to fetch data from the server. 
    //do i turn around and do: presenter.setView(this); and then the presenter takes 
    //over and uses the view to display the data? 
    } 
} 

這同樣是臭...很抱歉的長期職位,並感謝...

回答

6

你說得很對,因爲它既有View引用它的Presenter,也讓主持人引用了View,看起來有點不清楚。

的方式我看它,以及如何在MVP輪廓谷歌開發的網頁有MVP的兩種口味:

  1. 有一個不知道它的主持人,和「包裝」它,以期主持人。該視圖爲演示者提供了足夠的API來獲取/設置所關注的所有數據。此外,演示者必須知道視圖可以生成的所有事件類型,以便響應用戶交互。這是MPV part 1的方法。
  2. 主持人再次瞭解該視圖,但這次只能獲取/設置數據容量。演示者不關心視圖中的UI事件。相反,主持人提供了一個API供視圖在發言人以「onSomethingHappened()」方法的形式發生事件時調用/通知它。這允許我們捕獲演示者本身中的所有行爲/邏輯,並在視圖中發生某些事情時根據需要調用它。然後視圖可以以任何合適的方式處理低級別的事件 - 無論是使用GWT事件/小部件還是使用元素/ HTML(UiBinder/GWT性能最佳實踐)的原始DOM事件。這是MVP part 2的方法。

我更喜歡選項2,因爲它允許演示者完全專注於必要的行爲。該視圖可以根據需要處理widgets/html/event處理,並將其簡化爲調用演示者的「onSomething()」調用。這些小部件/事件實現可能是簡單或複雜的優化事件。主持人不受細節影響(並且未受到污染),因爲它只是得到通知。我覺得這個選項是一個更簡潔的演示和行爲分離。請注意,它也是Observer Pattern的1到1實現,因此View和Presenter之間的互連是必需的。

至於創作,我覺得Presenter是一個更強大的實體,儘管它扮演着Observer的角色。我會創建必要的演示者,然後將其傳遞給關注的角度。演示者然後可以控制視圖,並將視圖傳遞給自我引用。

至於你的製片人/消費者類比,我認爲主持人是消費者。視圖產生UI事件(用戶交互),演示者通過提供必要的行爲來響應。這應該是視圖和演示者之間唯一的聯繫點 - 視圖調用諸如「onSomethingHappened()」之類的方法,演示者完成這項工作。視圖永遠不會告訴主持人「fetchData()」或類似的東西。

我剛剛開始使用UiBinder + MVP自己,所以這正是我的想法。我希望它有幫助!

+0

另請參閱http://www.google.com/events/io/2010/sessions/gwt-continuous-build-testing.html,其中討論了他們如何在Google Wave(現爲Apache Wave)中使用MVP:演示者從不對於視圖而言,取而代之的是,視圖總是以適當的值回調給演示者;並且演示者完全控制演示狀態。儘管編輯器框架和/或單元小部件效果不佳,但它是一種有趣的方法。 –

+0

謝謝你的深思熟慮......我研究了文章和附件。我還沒有看到波浪會議(我會在稍後觀看)。我從來沒有真正使用過display.getClickHandler方法(即使我做了gwt-pure-java)。我總是有setter(display.setClickHandler)。我需要進一步思考。我可能沒有想到UiBinder及其在視圖創建和視圖放置中的作用...... – hba

0

從我開始這個主題並閱讀回覆已經有幾天了。我決定採取我的方法。我想我只是在這裏提到它。

再次,感謝您的深思熟慮的迴應......他們很有幫助。

由於filip-fku指出主持人是主要實體,因此我決定在我的mvp對象的生命週期管理期間繼續威脅他們。換句話說,視圖不會實例化演示者。演示者由其他演示者實例化(在某些時候,我將委派給Gin)。

演示者的builder可以訪問其相應的視圖,並向視圖注入演示者(通過構造函數)。

視圖本身要麼由builder實例化,要麼由UiBinder實例化爲更大視圖的一部分。在UiBinder實例化視圖的情況下,父視圖有一個getter。下面是這種情況的一個例子:

/*pojo for the parent ui-binder*/ 
public class Form implements FormPresenter.View { 
@UiField PromptView namePrompt; 
@override 
PromptPresenter.View getNamePromptDisplay() { 
    return namePrompt; //introduced into this pojo via @UiField 
} 
//bunch of view code 
}//end of the class 

然後在FormPresenter我做的:

private void buildNamePrompt() { 
    new PromptPresenter(display.getNamePromptDisplay(), etc....); 
} 

我已經基本上保持了MVP的生命週期類似於純java方法。一旦我從中得到了一些黃鱔,我會用杜松子酒重構它。

再次感謝。 P.S.如果你還沒有看到上面提到的I/O演示文稿,那麼值得一試。