我刚刚开始在一个广泛使用beansbinding(MVVM模式)的Java项目中使用GlazedList。
PluggableList允许我将源列表绑定到表,然后在运行时更改源列表。为了实现这一点,每个源列表都必须共享相同的ListEventPublisher和ReadWriteLock,因为PlugableList必须与其源共享一个锁和重新发布器。我通过创建一个静态发布者并锁定我的类来实现这一点,该类拥有潜在的源列表,在类的每个实例化中使用这些静态值来创建列表以及PlugableList,如下面的伪代码所示:
public class ModelClass
{
final static EventList LIST = new BasicEventList();
final static ListEventPublisher LISTEVENTPUBLISHER = LIST.getPublisher();
final static ReadWriteLock READWRITELOCK = LIST.getReadWriteLock();
final EventList sourceList =
new BasicEventList(LISTEVENTPUBLISHER, READWRITELOCK);
}
public class UiControllerClass
{
final PluggableList pluggableList =
new PluggableList(ModelClass.LISTEVENTPUBLISHER, ModelClass.READWRITELOCK);
// ... call pluggableList.setSource(someSourceList)
}
我对此有两个担忧:
(1) 由于UiController中某个组件的特定要求,我必须在模型中做出决定。这似乎违反了MVVM模式。
(2) 如果列表非常多并且频繁访问,共享锁可能会影响列表的性能,因为它们都共享同一个锁。否则,这些列表中的每一个都应该能够独立运行,而不必相互关心。
我是不是搞错了?有没有更好的方法可以让PluggableLists在ModelClass不必知道特殊UiControllerClass要求的情况下工作,并且不会对性能造成潜在影响?
我提出了一个优雅的解决方案,它既保留了MVVM模式,又消除了对共享锁和发布器的需求。
我创建了一个自定义列表转换,它扩展了PluggableList并覆盖了它的setSource方法。然后,新的源列表将与PluggableList创建的新列表同步(它将具有与PluggableList相同的发布者和锁)。
public class HotSwappablePluggableList<T>
extends PluggableList<T>
{
private EventList<T> syncSourceList = new BasicEventList<>();
private ListEventListener<T> listEventListener = null;
public HotSwappablePluggableList()
{
super(new BasicEventList<T>());
}
@Override
public void setSource(final EventList<T> sourceList)
{
getReadWriteLock().writeLock().lock();
try
{
if (listEventListener != null)
{
syncSourceList.removeListEventListener(listEventListener);
}
syncSourceList = sourceList;
final EventList<T> syncTargetList = createSourceList();
listEventListener = GlazedLists.syncEventListToList(syncSourceList, syncTargetList);
super.setSource(syncTargetList);
}
finally
{
getReadWriteLock().writeLock().unlock();
}
}
}