Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FirebaseListAdapter not pushing individual items for chat app - Firebase-Ui 3.1

I am making a chat app on Android that uses google firebase to store messages that users write to each other. To display these messages to the users I read them from the database and organize them into a custom ListView with a ListAdapter. This was working fine until I updated my dependencies, specifically firebase ui to:

com.firebaseui:firebase-ui:3.1.0

Now the code to construct the list adapter does not work, being:

adapter = new FirebaseListAdapter<ChatMessage>(FirebaseDatabase.getInstance().getReference("Lobbies").child(leaderID).child("Messages"), ChatMessage.class, R.layout.message, this) {
        @Override
        protected void populateView(View v, ChatMessage model, int position) {
            // Get references to the views of message.xml
            TextView messageText = (TextView)v.findViewById(R.id.message_text);
            TextView messageUser = (TextView)v.findViewById(R.id.message_user);
            TextView messageTime = (TextView)v.findViewById(R.id.message_time);

            // Set their text
            messageText.setText(model.getMessageText());
            messageUser.setText(model.getMessageUser());

            // Format the date before showing it
            messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
                    model.getMessageTime()));
        }
    };

To fix this issue, I updated the code to conform to the new firebase ui requirements, making the code become:

FirebaseListOptions<ChatMessage> options = new FirebaseListOptions.Builder<ChatMessage>()
            .setQuery(FirebaseDatabase.getInstance().getReference("Lobbies").child(leaderID).child("Messages"), ChatMessage.class).setLayout(R.layout.message).build();

    adapter = new FirebaseListAdapter<ChatMessage>(options) {
        @Override
        protected void populateView(View v, ChatMessage model, int position) {
            // Get references to the views of message.xml
            TextView messageText = v.findViewById(R.id.message_text);
            TextView messageUser = v.findViewById(R.id.message_user);
            TextView messageTime = v.findViewById(R.id.message_time);

            // Set their text
            messageText.setText(model.getMessageText());
            messageUser.setText(model.getMessageUser());

            // Format the date before showing it
            messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
                    model.getMessageTime()));
        }
    };

This code compiles fine now, but the listview is not displaying the data. Is there a specific right way to use the new firebase ui dependency to make the list adapter?

like image 648
Dylan Kane Avatar asked Nov 10 '17 17:11

Dylan Kane


2 Answers

In addition to what's been said in Peter's answer, according to FirebaseRecyclerAdapater latest api documentation, you can create a FirebaseRecyclerAdapter passing in a FirebaseRecyclerOptions instance which is created by a builder. In the builder you specify a lifecycle owner so you don't have to modify either its onStart or its onStop manually:

private fun MainActivity.setUpFirebaseRecyclerAdapter():
    FirebaseRecyclerAdapter<User, ListOnlineViewHolder> {

val options = FirebaseRecyclerOptions.Builder<User>()
        .setQuery(ONLINE_USERS.limitToLast(10), User::class.java)
        .setLifecycleOwner(this)
        .build()

return object : FirebaseRecyclerAdapter<User, ListOnlineViewHolder>(options){
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListOnlineViewHolder {
        return ListOnlineViewHolder(
                LayoutInflater.from(parent.context)
                        .inflate(R.layout.user_layout, parent, false))
    }
    override fun onBindViewHolder(holder: ListOnlineViewHolder, position: Int, model: User) {
        holder.bindMessage(model)
    }
}
}

The options builder is made up of a setQuery method which takes in a reference to the db and a model object; the setLifecycleOwner which takes in the activity that will trigger the adapter updates.

like image 80
glisu Avatar answered Nov 08 '22 19:11

glisu


To let the FirebaseRecyclerAdapter and FirebaseListAdapter show the data on the activity

You need to use this:

@Override
protected void onStart() {
super.onStart();
adapter.startListening();
}


@Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}

Since FirebaseListAdapter uses a listener to check for changes in the firebase database, then to being listening for data you need to add adapter.startListening() inside the onStart() to be able to show the data in the listview.

Then inside onStop() (when activity is stopped), you can use adapter.stopListening() to remove the listener and the data in the adapter.

Check this for more info: Adapter LifeCycle

Note:

If after using the above, you get a nullpointexception or cannot resolve symbol, you have to declare adapter as global variable and please check the below answer: Error in startListening()

like image 44
Peter Haddad Avatar answered Nov 08 '22 18:11

Peter Haddad