A free Firebase project (console.firebase.google.com)
An emulator or an Android phone
How it fits together
1Add form
2users.push()
3Realtime Database
4ValueEventListener
5ListAdapter cards
Build it step by step
1. Create the database
In the Firebase console, add an Android app with your package name (com.example.recyclerviewfirebase to copy the code unchanged) and download google-services.json into the app folder. Then open Realtime Database → Create database and choose test mode while you learn.
2. Add Firebase to the app
In app/build.gradle.kts, add the plugin and dependencies:
plugins {id("com.google.gms.google-services") version "4.5.0" apply false}
Then press Sync Now.
3. Describe one user
User has public name, email and age fields and an empty constructor. Firebase uses them to turn database data into objects and back. The key field is marked @Exclude, so it isn't saved.
4. Add users
users.push().setValue(user) saves a user under a new unique key in the users node. You can also add users by hand in the console.
5. Listen for changes
Add a ValueEventListener to users in onStart. Whenever anything changes, onDataChange receives every user. Turn each child into a User, remember its key, and build a list.
6. Show the list
MyAdapter is a ListAdapter. Call submitList(list) and DiffUtil works out what changed, so only those cards animate.
7. Delete
The delete icon calls users.child(user.key).removeValue(). The listener then sends the new list automatically.
8. Stop listening
Remove the listener in onStop, so the app doesn't use data in the background.
9. Run it
Add a user, then open the console and edit or add one there. Watch the app update instantly; open it on two phones to see them stay in sync.
If something goes wrong
"Could not read the database": check the database Rules. Test mode allows reads and writes for 30 days.
Fields are empty: the names in User must match the names in the database exactly.
Before you publish: replace test-mode rules with rules that require sign-in.
What's improved over the video
You can add and delete users from the app, cards animate smoothly with DiffUtil, there's an empty-state message, and the listener stops when the screen is hidden.
Files affected
Check what to add and what to replace before copying code.
Adds users, listens to the database while visible, and feeds the list.
MainActivity.java
packagecom.example.recyclerviewfirebase;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importandroid.widget.TextView;importandroid.widget.Toast;importandroidx.annotation.NonNull;importandroidx.appcompat.app.AppCompatActivity;importandroidx.recyclerview.widget.LinearLayoutManager;importandroidx.recyclerview.widget.RecyclerView;importcom.google.firebase.database.DataSnapshot;importcom.google.firebase.database.DatabaseError;importcom.google.firebase.database.DatabaseReference;importcom.google.firebase.database.FirebaseDatabase;importcom.google.firebase.database.ValueEventListener;importjava.util.ArrayList;importjava.util.List;/**
* A live list of users from Firebase Realtime Database. Add a user (here or in the Firebase console)
* and every phone running the app sees it appear instantly.
*/publicclassMainActivityextendsAppCompatActivity{privatefinalDatabaseReference users =FirebaseDatabase.getInstance().getReference("users");privateValueEventListener listener;privateMyAdapter adapter;TextView empty;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);Screens.setUp(this,R.layout.activity_main);EditText name =findViewById(R.id.name);EditText email =findViewById(R.id.email);EditText age =findViewById(R.id.age);Button add =findViewById(R.id.btnAdd);
empty =findViewById(R.id.textEmpty);RecyclerView recyclerView =findViewById(R.id.recyclerview);
adapter =newMyAdapter(user -> users.child(user.key).removeValue());
recyclerView.setLayoutManager(newLinearLayoutManager(this));
recyclerView.setAdapter(adapter);
add.setOnClickListener(v ->{String nameTXT = name.getText().toString().trim();if(nameTXT.isEmpty()){
name.setError(getString(R.string.need_name));return;}// push() creates a new unique key, so two users can share a name.
users.push().setValue(newUser(nameTXT, email.getText().toString().trim(), age.getText().toString().trim()));
name.setText("");
email.setText("");
age.setText("");});}@OverrideprotectedvoidonStart(){super.onStart();// Listen only while the screen is visible, and stop in onStop to save battery and data.
listener =newValueEventListener(){@OverridepublicvoidonDataChange(@NonNullDataSnapshot snapshot){List<User> list =newArrayList<>();for(DataSnapshot child : snapshot.getChildren()){User user = child.getValue(User.class);if(user !=null){
user.key = child.getKey();
list.add(user);}}
adapter.submitList(list);
empty.setVisibility(list.isEmpty()?View.VISIBLE:View.GONE);}@OverridepublicvoidonCancelled(@NonNullDatabaseError error){Toast.makeText(MainActivity.this,R.string.error_read,Toast.LENGTH_LONG).show();}};
users.addValueEventListener(listener);}@OverrideprotectedvoidonStop(){
users.removeEventListener(listener);super.onStop();}}