Java Vaadin 7中TabSheet中惰性加载选项卡内容的策略
我正在寻找一种方法,仅在选择选项卡之后,而不是之前,将内容加载到Vaadin TabSheet上的选项卡中,这是一个术语 Vaadin 7的延迟加载并不明显,因为在构建时需要每个选项卡的内容Java Vaadin 7中TabSheet中惰性加载选项卡内容的策略,java,tabs,lazy-loading,vaadin,vaadin7,Java,Tabs,Lazy Loading,Vaadin,Vaadin7,我正在寻找一种方法,仅在选择选项卡之后,而不是之前,将内容加载到Vaadin TabSheet上的选项卡中,这是一个术语 Vaadin 7的延迟加载并不明显,因为在构建时需要每个选项卡的内容 我在瓦丁论坛上读了这篇文章。我确实从客户端了解到,Vaadin已经是懒惰加载了。在选择选项卡之前,不会在浏览器中填充DOM。但我担心的是减轻服务器端的负载。该线程无法解决该问题。这里是一个完整的示例。稍后可以将其封装在专用类中。请注意,每次选定选项卡时,选定选项卡的内容都会更改。如果您需要延迟加载,但不需要
我在瓦丁论坛上读了这篇文章。我确实从客户端了解到,Vaadin已经是懒惰加载了。在选择选项卡之前,不会在浏览器中填充DOM。但我担心的是减轻服务器端的负载。该线程无法解决该问题。这里是一个完整的示例。稍后可以将其封装在专用类中。请注意,每次选定选项卡时,选定选项卡的内容都会更改。如果您需要延迟加载,但不需要每次刷新,我将创建一个布尔加载字段,并使刷新依赖于它。与直觉相反,您可以通过提供渴望的构造函数参数使选项卡变得渴望。例如,它对于显示的第一个选项卡很有用
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
import com.vaadin.ui.TextField;
public class TablesFrame extends CustomComponent {
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
LazyTab tab = (LazyTab) event.getTabSheet().getSelectedTab();
tab.refresh();
}
}
private abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private LazyTab tab1 = new LazyTab(true) {
@Override
Component build() {
return new TextField("1");
};
};
private LazyTab tab2 = new LazyTab() {
@Override
Component build() {
return new TextField("2");
};
};
public TablesFrame() {
TabSheet ts = new TabSheet();
ts.addSelectedTabChangeListener(new LazyTabChangeListener());
ts.addTab(tab1, "Tab1");
ts.addTab(tab2, "Tab2");
setCompositionRoot(ts);
}
}
更新也可以将TabSheet子类化。这样,您也可以使用常规选项卡,并拥有TabSheet的所有操作。请注意,这里的急切懒散选项卡和常规选项卡是不同的,因为懒散选项卡将重新加载
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
public class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
public static abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
public abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}
如果您想以同样的方式使用accordion,我不会将tabsheet子类化,而是通过decorator模式实现该功能。Accordion将TabSheet子类化,因此它应该是可管理的。这里是一个完整的示例。稍后可以将其封装在专用类中。请注意,每次选定选项卡时,选定选项卡的内容都会更改。如果您需要延迟加载,但不需要每次刷新,我将创建一个布尔加载字段,并使刷新依赖于它。与直觉相反,您可以通过提供渴望的构造函数参数使选项卡变得渴望。例如,它对于显示的第一个选项卡很有用
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
import com.vaadin.ui.TextField;
public class TablesFrame extends CustomComponent {
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
LazyTab tab = (LazyTab) event.getTabSheet().getSelectedTab();
tab.refresh();
}
}
private abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private LazyTab tab1 = new LazyTab(true) {
@Override
Component build() {
return new TextField("1");
};
};
private LazyTab tab2 = new LazyTab() {
@Override
Component build() {
return new TextField("2");
};
};
public TablesFrame() {
TabSheet ts = new TabSheet();
ts.addSelectedTabChangeListener(new LazyTabChangeListener());
ts.addTab(tab1, "Tab1");
ts.addTab(tab2, "Tab2");
setCompositionRoot(ts);
}
}
更新也可以将TabSheet子类化。这样,您也可以使用常规选项卡,并拥有TabSheet的所有操作。请注意,这里的急切懒散选项卡和常规选项卡是不同的,因为懒散选项卡将重新加载
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
public class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
public static abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
public abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}
如果您想以同样的方式使用accordion,我不会将tabsheet子类化,而是通过decorator模式实现该功能。Accordion将TabSheet子类化,因此它应该是可管理的。下面是一个编译上述建议的实现:
public abstract class LazyTab {
Component comp;
private boolean eager;
private boolean cached;
public static LazyTab of(boolean eager, boolean cached, Supplier<Component> componentSupplier) {
return new LazyTab(eager, cached) {
@Override
protected Component build() {
return componentSupplier.get();
}
};
}
protected LazyTab(boolean eager, boolean cached) {
this.eager = eager;
this.cached = cached;
if (eager) comp = build();
}
protected abstract Component build();
public final void refresh() {
if ((comp == null) ||!cached) comp = build();
}
/**
* @return get component on demand (depends on eager and cached properties)
*/
public final Component getComponent() {
return comp;
}
public static class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
}
public static class LazyTabChangeListener implements TabSheet.SelectedTabChangeListener {
@Override
public void selectedTabChange(TabSheet.SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}
以下是上述建议的实施方案:
public abstract class LazyTab {
Component comp;
private boolean eager;
private boolean cached;
public static LazyTab of(boolean eager, boolean cached, Supplier<Component> componentSupplier) {
return new LazyTab(eager, cached) {
@Override
protected Component build() {
return componentSupplier.get();
}
};
}
protected LazyTab(boolean eager, boolean cached) {
this.eager = eager;
this.cached = cached;
if (eager) comp = build();
}
protected abstract Component build();
public final void refresh() {
if ((comp == null) ||!cached) comp = build();
}
/**
* @return get component on demand (depends on eager and cached properties)
*/
public final Component getComponent() {
return comp;
}
public static class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
}
public static class LazyTabChangeListener implements TabSheet.SelectedTabChangeListener {
@Override
public void selectedTabChange(TabSheet.SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}
将虚拟面板放入其中,并捕获TabSelected事件或其他来构建真实视图将虚拟面板放入其中,并捕获TabSelected事件或其他来构建真实视图为什么要扩展CustomComponent?为什么不将TabSheet子类化?作为一个简单的例子,它是否重要?这不是我的产品代码,而是帮助他人的快捷方式。为你自己量身定做代码,或者忽略它,这不是批评,而是严肃的问题。我不清楚定制组件的目的。我想知道通过子类化TabSheet来采用您的方法是否可行/可取。请参阅在您的评论之前编辑的更新:P。这里没有避免继承的特殊原因。碰巧我是这样写样本的。仔细想想,最好将tabsheet子类化,这样您也可以使用常规选项卡,并拥有tabsheet的所有操作。请注意,在这里,急切的懒虫标签和普通标签是不同的,因为懒虫标签会重新加载。答案很棒。我想补充一点,你的LazyTab也可以是一个界面。这样,每个选项卡本身都可以实现它,但它允许选项卡本身扩展它喜欢的内容,如VerticalLayout、CustomComponent或CssLayout。此外,在有选项卡的类中,您可以引用选项卡本身,有时更容易使用quick'n'dirty,只需处理selectedTabChange中的所有逻辑即可。您可以将一个临时组件放入选项卡中,如CssLayout,然后初始化真实视图并在selectedTabChange中将其关闭。为什么要扩展CustomComponent?为什么不将TabSheet子类化?作为一个简单的例子,它是否重要?这不是我的产品代码,而是帮助他人的快捷方式。为你自己量身定做代码,或者忽略它,这不是批评,而是严肃的问题。我不清楚定制组件的目的。我想知道通过子类化TabSheet来采用您的方法是否可行/可取。请参阅在您的评论之前编辑的更新:P。这里没有避免继承的特殊原因。碰巧我是这样写样本的。仔细想想,最好将tabsheet子类化,这样您也可以使用常规选项卡,并拥有tabsheet的所有操作。请注意,在这里,急切的懒虫标签和普通标签是不同的,因为懒虫标签会重新加载。答案很棒。我想补充一点,你的LazyTab也可以是一个界面。这样,每个选项卡本身都可以实现它,但它允许选项卡本身扩展它喜欢的内容,如VerticalLayout、CustomComponent或CssLayout。还有,在班里呢 你有标签页,你可以有标签页本身的引用,有时候玩quick'n'dirty更容易,只需注意selectedTabChange中的所有逻辑即可。您可以将一个临时组件放入选项卡中,如CssLayout,然后初始化真实视图并在selectedTabChange中将其切换出去。