仅使用geofire检索3英里范围内的用户列表

问题描述 投票:0回答:3

我正在尝试仅检索当前用户位置3英里范围内的用户列表。我正在使用recyclerView列出用户,也正在使用geofire来查询密钥,并且正在使用firebase来存储我的用户。当我尝试仅检索3英里以内的用户列表时,它将为我提供所有用户,包括3英里以内的用户。有人可以帮我解决这个问题。下面是我的代码。在此先感谢

MainClass检索数据

@Override
public void onSuccess(Location location) {

    Double latitude=location.getLatitude();
    Double longitude=location.getLongitude();

    Geocoder geocoder=new Geocoder(NewsFeedActivity.this, Locale.getDefault());


     firebaseDatabase=FirebaseDatabase.getInstance().getReference("Users");
    GeoFire geoFire=new GeoFire(firebaseDatabase.child("locals"));


    final GeoQuery geoQuery=geoFire.queryAtLocation(new GeoLocation(latitude,longitude),3);

    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(final String key, GeoLocation location) {

            firebaseDatabase.addValueEventListener(new ValueEventListener() {


                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    list=new ArrayList<Users>();

                    for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren()){
                        Users my=dataSnapshot1.getValue(My.class);
                        list.add(my);

                    }

                adapter=new MyAdapter(MainActivity.this,list);
                            recycler.setAdapter(adapter);


                    adapter=new MyAdapter(MainActivity.this,list);
                    recycler.setAdapter(adapter);

                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });
        }

        @Override
        public void onKeyExited(String key) {

        }

        @Override
        public void onKeyMoved(String key, GeoLocation location) {

        }

        @Override
        public void onGeoQueryReady() {

        }

        @Override
        public void onGeoQueryError(DatabaseError error) {

            System.err.println("There was an error with this query: " + error);


        }
    });

recyclerView的适配器类

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    Context context;
    private ArrayList<UserInformation> users;



    public MyAdapter(Context c,ArrayList<UserInformation> u){

        context=c;
        users=u;

    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.cardview,parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.user_name.setText(users.get(position).getBusinessname());
        holder.address.setText(users.get(position).getAddress());


    }

    @Override
    public int getItemCount() {
        return users.size();
    }


    class MyViewHolder extends RecyclerView.ViewHolder{


        TextView user_name,address;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);

            user_name=(TextView)itemView.findViewById(R.id.user_name);
            address=(TextView)itemView.findViewById(R.id.user_address);
        }
    }
}


     //Users Class

    public class Users {

    public String usersname;
    public String address;
    public String phonenumber;

    public Users(String usersname, String address, String phonenumber) {
        this.usersname = usersname;
        this.address = address;
        this.phonenumber = phonenumber;
    }

    public Users(){

    }

    public String getBusinessname() {
        return usersname;
    }

    public void setBusinessname(String businessname) {
        this.usersname = usersname;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhonenumber() {
        return phonenumber;
    }

    public void setPhonenumber(String phonenumber) {
        this.phonenumber = phonenumber;
    }
}
android firebase firebase-realtime-database geofire
3个回答
1
投票

您的地理查询可在距指定位置3公里的范围内正确搜索关键字:

firebaseDatabase=FirebaseDatabase.getInstance().getReference("Users");
GeoFire geoFire=new GeoFire(firebaseDatabase.child("locals"));

final GeoQuery geoQuery=geoFire.queryAtLocation(new GeoLocation(latitude,longitude),3);

但是,当GeoFire在该范围内找到一个密钥并调用onKeyEntered时,您将ValueEventListener添加到整个Users节点:

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(final String key, GeoLocation location) {
        firebaseDatabase.addValueEventListener(new ValueEventListener() {

因此,对于地理查询范围内的每个键,您都会加载所有用户。如果范围内有多个密钥,则为每个密钥加载所有用户,并每次创建一个适配器。充其量是杂乱和浪费的,但是我认为在这种情况下,这也是为什么您的代码没有执行您想要的操作的原因。

[我的最佳猜测是,地理查询中的每个键都标识Users下的一个节点,并且您只想在每次调用onKeyEntered方法时加载that用户的节点。这样,当地理查询范围内有多个键时,就会在该范围内逐一加载每个用户。

如果是这种情况,您将需要在onKeyEntered中使用此侦听器:

firebaseDatabase.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        Users my=dataSnapshot.getValue(My.class);
        list.add(my);
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        throw databaseError.toException(); // never ignore possible errors
    }
});

我在这里所做的一些更改:

  • 不是加载所有用户,而是为(或输入)地理查询范围的每个键加载一个用户。
  • 使用addListenerForSingleValueEvent,而不是连续的侦听器。这样,您只需为用户获取一次数据,而不必不断添加越来越多的侦听器。
  • 调用adapter.notifyDataSetChanged();而不是为属于地理查询范围的每个键创建新的适配器。
  • 您仍然需要做的事情:

  • 仅初始化适配器一次,onKeyEntered外部,将其传递给list
  • 然后在onKeyEntered触发时加载该用户的数据,将其添加到list,并告诉适配器它需要使用adapter.notifyDataSetChanged()重新绘制。


0
投票

您可以指定中心和半径several ways。这是一种方法:


0
投票

我在弗兰克·范·普菲伦(Frank Van Puffelen)的帮助下解决了这个问题。这是我所做的

© www.soinside.com 2019 - 2024. All rights reserved.