【问题标题】:Adapter with hasStableIds using GUIDs or Strings as Ids具有使用 GUID 或字符串作为 Id 的 hasStableIds 的适配器
【发布时间】:2014-11-27 22:38:55
【问题描述】:

我正在实现一个自定义ArrayAdapter<T>,我想将hasStableIds 设置为true。但是我的 T 项的 id 是 StringsgetItemId 方法返回 longs

所以,我目前正在做的是:

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public long getItemId(int position) {
    return this.getItem(position).getId().hashCode();
}

getId() 返回一个字符串。

这是使用字符串 ID 的正确解决方案吗?
特别是在这种情况下,String Id 是 GUID,有没有更好的选择?

【问题讨论】:

    标签: android listview android-arrayadapter baseadapter


    【解决方案1】:

    您不想使用hashCode(),因为这样,两个不同的 GUIDS 可能会产生相同的 ID。

    只需编写映射代码。像这样的...

    private static class GuidToIdMap {
        private final Map<String, Long> guidToIdMapping = new HashMap<String, Long>();
        private final Map<Long, String> idToGuidMapping = new HashMap<Long, String>();
    
        private long idGenerator = 0;
    
        public long getIdByGuid(final String guid) {
            if ( ! guidToIdMapping.containsKey(guid)) {
                final long id = idGenerator++;
                guidToIdMapping.put(guid, id);
                idToGuidMapping.put(id,   guid);
            }
            return guidToIdMapping.get(guid);
        }
    
        public String getGuidById(final long id) {
            if (idToGuidMapping.containsKey(id)) {
                return idToGuidMapping.get(id);
            }
            return null;
        }
    }
    
    
    private final GuidToIdMap guidToIdMap = new GuidToIdMap();
    
    @Override
    public boolean hasStableIds() {
        return true;
    }
    
    @Override
    public long getItemId(int position) {
        final String guid = this.getItem(position).getId();
        return guidToIdMap.getIdByGuid(guid);
    }
    
    // Use guidToIdMap.getGuidById(id) where the Android Framework passes you the generated id
    

    性能影响可以忽略不计....

    【讨论】:

    • 使用最终长 id = new Random().nextLong();而不是 idGenerator 变量。使用 idGenerator 可以得到重复的 id。
    • @rajeswariratala 请解释如何获得“idGenerator”的重复项?!
    • 由于它不同步,我得到了重复。您可以使用 atomiclong 和 getAndIncrement() 或随机 long。
    • 奇数。很可能您没有在 Android UI thread 上发布 GUI 任务。考虑 AsyncTasks 做后台工作,其结果需要由 GUI 处理。
    【解决方案2】:

    只要返回的 id 在更改后对于同一对象保持相同并且它是唯一的,如 hasStableIds 的 javadoc 中所述,就可以了

    【讨论】:

    • @Niels 确定!但无论如何,我的说法是对的。相同的字符串是相同的哈希值,这是 java 固有的,即使它不是相同的字符串但意外地具有相同的哈希值。
    【解决方案3】:

    您可以这样做: 返回 UUID.getLeastSignificantBits()

    P/s:你可能不应该。 long 的大小为 8 个字节,而 UUID 的大小为 16 个字节。因此UUID 不能存储在long 中。来自Wikipedia

    需要选择标识符大小和生成过程,以使这在实践中足够不可能。 因此,两个不同的 UUID 可以具有相同的leastSignificantBits

    【讨论】:

      【解决方案4】:

      不,你错了 getItemId 有两个方法签名,其中一个返回 long 每个文档: https://developer.android.com/reference/android/widget/Adapter.html#getItemId(int)

      【讨论】:

      • 其实getItemId方法只有一个,而且返回的时间长,发帖前请检查自己的信息。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多