Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using GeoFire to Populate Firebase Recycler View in android

I want to populate my recycler view so that, I can see who are the people/places nearby. I am using GeoFire to Query my database, which looks something like this.

 GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latLngCenter.latitude, latLngCenter.longitude), 0.1);
        geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
            @Override
            public void onKeyEntered(String key, GeoLocation location) {
                System.out.println(String.format("Key %s entered the search area at [%f,%f]", key, location.latitude, location.longitude));
                Log.e("TAG", key + location.latitude + location.longitude);

            }

            @Override
            public void onKeyExited(String key) {
                System.out.println(String.format("Key %s is no longer in the search area", key));
            }

            @Override
            public void onKeyMoved(String key, GeoLocation location) {
                System.out.println(String.format("Key %s moved within the search area to [%f,%f]", key, location.latitude, location.longitude));
                Log.e("TAG", key + location.latitude + location.longitude);
            }

            @Override
            public void onGeoQueryReady() {
                System.out.println("All initial data has been loaded and events have been fired!");
            }

            @Override
            public void onGeoQueryError(DatabaseError error) {
                System.err.println("There was an error with this query: " + error);
            }
        });

and I am using this Firebase RecyclerView

 RecyclerView recycler = (RecyclerView) findViewById(R.id.RecyclerView);
    recycler.setHasFixedSize(true);
    recycler.setLayoutManager(new LinearLayoutManager(this));

    FirebaseRecyclerAdapter<Chat, ChatHolder> mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, R.layout.recyclerview, ChatHolder.class, mUsers) {


        @Override
        public void populateViewHolder(final ChatHolder chatMessageViewHolder, final Chat chatMessage, int position) {


                    chatMessageViewHolder.setName(chatMessage.getName());
                    chatMessageViewHolder.setText(chatMessage.getText());
                    chatMessageViewHolder.setTimestamp(chatMessage.getTimestamp());



        }
    };
    recycler.setAdapter(mAdapter);

with these Chat Holder class and chat object class

public static class ChatHolder extends RecyclerView.ViewHolder {
    View mView;

    public ChatHolder(View itemView) {
        super(itemView);
        mView = itemView;
    }



    public void setName(String name) {
        TextView field = (TextView) mView.findViewById(R.id.textViewName);
        field.setText(name);
    }

    public void setText(String text) {
        TextView field = (TextView) mView.findViewById(R.id.textViewMessage);
        field.setText(text);
    }

    public void setTimestamp(String text) {
        TextView field = (TextView) mView.findViewById(R.id.textViewTime);
        field.setText(text);
    }
}

public static class Chat {

    String name;
    String text;
    String uid;
    String timestamp;

    public Chat() {
    }

    public Chat(String name, String uid, String message, String timestamp) {
        this.name = name;
        this.text = message;
        this.uid = uid;
        this.timestamp = timestamp;
    }

    public String getName() {
        return name;
    }

    public String getUid() {
        return uid;
    }

    public String getText() {
        return text;
    }

    public String getTimestamp() {
        return timestamp;
    }
}

Currently this, adapter which is provided in FirebaseUI library, populates recyclerview so that, only one reference is used and all child events are shown in the view, Now, I want to populate my recyclerView so that when ever a key enters it populates my recyclerview based on my key = to my reference, this how my firebase database looksmy firebase database

like image 289
virsam Avatar asked Aug 07 '16 10:08

virsam


1 Answers

It'll be simpler to push all data (which is also uid) you have retrieved from geofire to a new node to store geofire results in firebase, something like

my-node //your new firebase node to store all uids retrieved from geofire
- {chatUid}: true //true is just a dummy data, you can use anything else except null and empty string.
- {chatUid}: true
- ...

and set FirebaseRecyclerAdapter ref to that node.

DatabaseReference ref = FirebaseDatabase.getInstance().getReference("my-node");
FirebaseRecyclerAdapter fra = new FirebaseRecyclerAdapter<Boolean, MyVH>(Boolean.class, R.layout.my_layout, MyVH.class, ref) { ... }

and then, in populateViewHolder() method in your implementation of FirebaseRecyclerAdapter, you can use the String key to fetch data from main node that contains the data.

public void populateViewHolder(MyVH viewHolder, Boolean model, int position){
    // Get references of child views
    final TextView nameTextView = viewHolder.getItemView().findViewById(R.id.my_name_text_view_in_vh_layout);
    final TextView addressTextView = viewHolder.getItemView().findViewById(R.id.my_address_text_view_in_vh_layout);

    // Key in this position.
    String key = getRef(position).key;

    // Query the full data of the current key located in the `main-data-node`
    FirebaseDatabase.getInstance().getReference("main-data-node").child(key).addValueEventListener(new ValueEventListener(){
        ... //Truncated onCancelled

        @Override
        public void onDataChange(snap: DataSnapshot){
            MyDataModel model = snap.getValue(MyDataModel.class);

            nameTextView = model.getName();
            addressTextView = model.getAddress();
        }
    }
}

// The data model class
public class MyDataModel { 
    private String name; 
    private String address; 
    ... // Truncated getter, setter, constructor
}

For any changes in geofire result, just push those results to my-node, and it will automatically informs your FirebaseRecyclerAdapter.

P.S. I'm too lazy to match my solution to your data model (sorry), so I made a simplified sample class, so if anyone stumbled upon this, they can understand it easier.

P.S.S. It's been a while since I code in java, I mainly use kotlin (and you soon should too lol), so, if there're some syntax mistakes out there, feel free to edit.

like image 107
Moses Aprico Avatar answered Oct 08 '22 23:10

Moses Aprico