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?
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.
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
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With