ListDataProvider.getList().remove 不使用 KeyProvider

ListDataProvider.getList().remove doesn't use the KeyProvider

调用 ListDataProvider.getList().remove(...) 不使用构造函数中传递的 KeyProvider。这是一个 GWT 错误还是它应该像这样工作? 我在下面附上了相关的单元测试。

谢谢,

    TestVO ri1 = new TestVO();
    ri1.setId(null);
    ri1.setName("msg1");
    TestVO ri2 = new TestVO();
    ri2.setId(null);
    ri2.setName("msg2");
    TestVO ri3 = new TestVO();
    ri3.setId(null);
    ri3.setName("msg2");

    ListDataProvider<TestVO> ldp = new ListDataProvider<>(new ProvidesKey<TestVO>() {
      @Override
      public Object getKey(TestVO pItem) {
        System.out.println("this never gets invoked");
        return pItem.getMessageType();
      }
    });
    ldp.setList(Lists.newArrayList(ri1, ri2));

    ldp.getList().remove(ri3);

    //this currently fails, actual size is 1 as it removes ri2
    assertEquals(2, ldp.getList().size());

不,这不是错误,也不,它不使用您提供的 getKey 实现来查找该列表中的元素,因为该方法用于其他操作。忍耐一下...

ListDataProvider 使用实现 List 接口的 ListWrapperListWrapper 由保存对象的普通 List 支持。 ListWrapper 具有您正在使用的方法(添加、设置、删除等)的实现,这些方法操纵您传递给 Lists.newArrayList(ri1, ri2)List

此操作是通过调用 List 接口的标准操作等方式完成的。因此,被调用以确定应删除哪个对象的是 indexOf ,让我们说 ArrayList (这就是您要传递的内容,所以这就是正在使用的内容)使用(正如您所期望的那样) equals TestVO 的方法,如果你没有覆盖,你可以在 Object class.

中找到

您提供的 getKey 方法用于识别行列表中的行(在您使用的显示中,如 DataGrid)。这可以在 AbstractDataProvider 中找到。这个调用你的方法的方法被其他方法调用(看看我在那里做了什么:P),以便识别需要一些操作的行。例如更新 DataGrid 中的一行。确定更新哪一行的方法是您提供的方法。因此,如果您的实现不提供唯一键,您将看到使用相同键对所有行进行更新的指示。所以要小心。

  /**
   * Get the key for a list item. The default implementation returns the item
   * itself.
   *
   * @param item the list item
   * @return the key that represents the item
   */
  public Object getKey(T item) {
    return keyProvider == null ? item : keyProvider.getKey(item);
  }

indexOfArrayList

中的实现
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

这是GWT的实现

/**
 * Construct a new {@link ListWrapper} that delegates flush calls to the
 * specified delegate.
 *
 * @param list the list to wrap
 * @param delegate the delegate
 * @param offset the offset of this list
 */
private ListWrapper(List<T> list, ListWrapper delegate, int offset) {
  this.list = list;
  this.delegate = delegate;
  this.offset = offset;
}

@Override
public void add(int index, T element) {
  try {
    list.add(index, element);
    minModified = Math.min(minModified, index);
    maxModified = size();
    modified = true;
    flush();
  } catch (IndexOutOfBoundsException e) {
    throw new IndexOutOfBoundsException(e.getMessage());
  }
}
@Override
public T remove(int index) {
  try {
    T toRet = list.remove(index);
    minModified = Math.min(minModified, index);
    maxModified = size();
    modified = true;
    flush();
    return toRet;
  } catch (IndexOutOfBoundsException e) {
    throw new IndexOutOfBoundsException(e.getMessage());
  }
}

@Override
public boolean remove(Object o) {
  int index = indexOf(o);
  if (index == -1) {
    return false;
  }
  remove(index);
  return true;
}

public void setList(List<T> listToWrap) {
  listWrapper = new ListWrapper(listToWrap);
  listWrapper.minModified = 0;
  listWrapper.maxModified = listWrapper.size();
  listWrapper.modified = true;
  flush();
}

public List<T> getList() {
  return listWrapper;
}