从 geoQuery 向 recyclerView 添加独特的项目
Add unique items to recyclerView from geoQuery
我创建了一个应用程序来显示我附近用户的项目。
我使用 geoQuery
找到了我附近的人,如果他们在我附近,我会在数据库中搜索他们拥有的物品,然后用他们填充 RecyclerView
。
我使用:
List<DiscoverItems> items = new ArrayList<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
String UserID = key;
if (!UserID.equals(auth.getUid())) {
db.collection("Users").document(UserID).collection("MyItems").get().addOnCompleteListener(task_count -> {
if (task_count.isSuccessful()) {
for (DocumentSnapshot document_near : task_count.getResult()) {
items.add(new DiscoverItems(document_near.getString("ItemID")));
}
}
});
}
discoverItemAdapter = new DiscoverItemAdapter(items, listener);
rv_NearMeItems.setAdapter(discoverItemAdapter);
}
@Override
public void onKeyExited(String key) {
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
}
@Override
public void onGeoQueryReady() {
}
@Override
public void onGeoQueryError(DatabaseError error) {
}
});
但是,我的问题是如果某些用户拥有相同的物品,因为它会在 recyclerView 中出现两次,而我希望它具有独特的物品。
是否有任何解决方案可以让我先检查我的项目列表是否重复,然后再添加它们?
我尝试执行以下操作:
List<DiscoverItems> items= new ArrayList<>();
Set<DiscoverItems> itemkset = new HashSet<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener( new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
String UserID = key;
if (!UserID.equals( auth.getUid() )) {
db.collection( "Users" ).document( UserID ).collection( "MyItems" ).get().addOnCompleteListener( task_count -> {
if (task_count.isSuccessful()) {
for (DocumentSnapshot document_near : task_count.getResult()) {
itemset.add( new DiscoverItems( document_near.getString( "ItemID" ) ) );
}
}
} );
}
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(itemset));
for (DiscoverItems item: itemsWithoutDuplicates){
items.add(item);
}
discoverItemAdapter = new DiscoverItemAdapter(items, listener);
rv_NearMeItems.setAdapter(discoverItemAdapter);
}
但这不起作用,因为如果我有 2 个用户,onKeyEntered
将被调用两次。对于第一个用户,它将添加到 itemset
让我们说 4 个不相同的项目,一切都会好的。然后它会调用第二个用户,它也会向项目集中添加 3 个不相同的项目,这样就可以了。
我错过了什么吗?
因为使用上面的代码我得到了多个项目。
谢谢
我不知道你对象的复杂度,但你可以尝试将 List<>
int 更改为 Set<>
。一般来说,Set
是包含 没有重复元素的集合 (例如,基于他们的哈希码)。
1) 对象比较
首先,您必须覆盖 DiscoverItems
class 中的 equals()
和 hashCode()
才能使用基于散列的集合(如 HashSet
)。
您可以在 Android Studio 中生成这些方法,并根据您可以说“这两个对象相同”的字段来选择。有时不需要比较所有字段(例如,您可以仅使用名称或某些 ID)。
你的情况,你必须比较你传递给 DiscoverItems
class 的构造函数的这个字段。它看起来像那里:
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
DiscoverItems that = (DiscoverItems) object;
return Objects.equals(itemID, that.itemID);
}
@Override
public int hashCode() {
return Objects.hash(itemID);
}
2) 合集
因此更改为:
List<DiscoverItems> items = new ArrayList<>();
进入:
Set<DiscoverItems> items = new HashSet<>();
当你需要在一个地方检查时,你可以转换:
List ---> Set ---> List
例如:
Set<DiscoverItems> set = new HashSet<>(items);
if (items.size() == set.size()) {
// No duplicates, use original list
} else {
// Duplicates removed, use new list
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);
}
或没有附加条件:
Set<DiscoverItems> set = new HashSet<>(items);
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);
或单行:
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(items));
提示
您应该将 class 命名为 DiscoverItem
而不是 DiscoverItems
。因为代表的是一件,不是很多。
我创建了一个应用程序来显示我附近用户的项目。
我使用 geoQuery
找到了我附近的人,如果他们在我附近,我会在数据库中搜索他们拥有的物品,然后用他们填充 RecyclerView
。
我使用:
List<DiscoverItems> items = new ArrayList<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
String UserID = key;
if (!UserID.equals(auth.getUid())) {
db.collection("Users").document(UserID).collection("MyItems").get().addOnCompleteListener(task_count -> {
if (task_count.isSuccessful()) {
for (DocumentSnapshot document_near : task_count.getResult()) {
items.add(new DiscoverItems(document_near.getString("ItemID")));
}
}
});
}
discoverItemAdapter = new DiscoverItemAdapter(items, listener);
rv_NearMeItems.setAdapter(discoverItemAdapter);
}
@Override
public void onKeyExited(String key) {
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
}
@Override
public void onGeoQueryReady() {
}
@Override
public void onGeoQueryError(DatabaseError error) {
}
});
但是,我的问题是如果某些用户拥有相同的物品,因为它会在 recyclerView 中出现两次,而我希望它具有独特的物品。
是否有任何解决方案可以让我先检查我的项目列表是否重复,然后再添加它们?
我尝试执行以下操作:
List<DiscoverItems> items= new ArrayList<>();
Set<DiscoverItems> itemkset = new HashSet<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener( new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
String UserID = key;
if (!UserID.equals( auth.getUid() )) {
db.collection( "Users" ).document( UserID ).collection( "MyItems" ).get().addOnCompleteListener( task_count -> {
if (task_count.isSuccessful()) {
for (DocumentSnapshot document_near : task_count.getResult()) {
itemset.add( new DiscoverItems( document_near.getString( "ItemID" ) ) );
}
}
} );
}
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(itemset));
for (DiscoverItems item: itemsWithoutDuplicates){
items.add(item);
}
discoverItemAdapter = new DiscoverItemAdapter(items, listener);
rv_NearMeItems.setAdapter(discoverItemAdapter);
}
但这不起作用,因为如果我有 2 个用户,onKeyEntered
将被调用两次。对于第一个用户,它将添加到 itemset
让我们说 4 个不相同的项目,一切都会好的。然后它会调用第二个用户,它也会向项目集中添加 3 个不相同的项目,这样就可以了。
我错过了什么吗? 因为使用上面的代码我得到了多个项目。
谢谢
我不知道你对象的复杂度,但你可以尝试将 List<>
int 更改为 Set<>
。一般来说,Set
是包含 没有重复元素的集合 (例如,基于他们的哈希码)。
1) 对象比较
首先,您必须覆盖 DiscoverItems
class 中的 equals()
和 hashCode()
才能使用基于散列的集合(如 HashSet
)。
您可以在 Android Studio 中生成这些方法,并根据您可以说“这两个对象相同”的字段来选择。有时不需要比较所有字段(例如,您可以仅使用名称或某些 ID)。
你的情况,你必须比较你传递给 DiscoverItems
class 的构造函数的这个字段。它看起来像那里:
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
DiscoverItems that = (DiscoverItems) object;
return Objects.equals(itemID, that.itemID);
}
@Override
public int hashCode() {
return Objects.hash(itemID);
}
2) 合集
因此更改为:
List<DiscoverItems> items = new ArrayList<>();
进入:
Set<DiscoverItems> items = new HashSet<>();
当你需要在一个地方检查时,你可以转换:
List ---> Set ---> List
例如:
Set<DiscoverItems> set = new HashSet<>(items);
if (items.size() == set.size()) {
// No duplicates, use original list
} else {
// Duplicates removed, use new list
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);
}
或没有附加条件:
Set<DiscoverItems> set = new HashSet<>(items);
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);
或单行:
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(items));
提示
您应该将 class 命名为 DiscoverItem
而不是 DiscoverItems
。因为代表的是一件,不是很多。