ZOFTINO.COM android and web dev tutorials

Firebase Cloud Firestore Database Tutorial Android Example

Firebase’s Firestore database is a NoSQL database hosted on cloud. Firestore database can be used in android, ios and web applications and can be accessed using various Firestore SDKs provided by Firebase. It can also be accessed using REST API.

Firestore database is useful for android applications because you don’t need to develop remote services to access remote data.

Table of Contents

Cloud Firestore Database Data Model

Firestore database doesn’t store data in tables containing columns and rows. You don’t need to even define schemas. It stores data in documents with each document containing set of name and value pairs. Document can contain nested objects meaning for a key in a document value can be set of key value pairs.

These documents are held in collections. Each document should belong to a collection. Document can contain collections allowing you create hierarchical data.

Firestore support various data data types. Following picture shows firestore database data model.

firebase firestore database data model

Cloud Firestore Database Features

Firestore database provides flexible data model as discussed above. It allows you to query collection with filters to get list of matching documents with sort option. It offers efficient way of providing real time updates to connected devices using data synchronization.

It offers offline support meaning when there is no network connection, app can perform insert, select, update operations on documents as Firestore caches actively used data on the device and synchronizes local changes to cloud Firestore once network connection is available.

Firestore supports atomic batch operations and transactions to guarantee data consistency.

Enable Firestore

Below are the steps to enable Firestore using Firebase console.

  • Login to Firebase console.
  • Create Firebase project.
  • firebase console add project
  • Go to database section, enable cloud Firestore database.
  • firebase console enable cloud firestore database

Setup Project

Below are the steps you need to follow to make your project ready to use Firestore. Or you can use Firebase assistant tool in android studio to automate the project setup. You can open Firebase assistant by clicking tools > firebase. Then expand one of the firebase products, then click a link and then connect to firebase and complete the setup.

Add Firebase SDK to project

In the project overview section of Firebase console, click add Firebase to android project.

firebase console add firebase to android app

In the form just enter the package name used in your project in android studio and submit. On the next screen, you will see download google-services.json file option. Download it and add the file to your project by placing it under app.

To add Firebase SDK to your project, add below entries to project level and app level build.gradle files. Add below entry to bottom of app level build file.

plugin: 'com.google.gms.google-services'

Add below entry to project level build file as dependencies.

classpath 'com.google.gms:google-services:3.1.0'

Add Firestore library to project

Then add Firestore library to app level gradle.build file

implementation 'com.google.firebase:firebase-firestore:11.6.0'

Using Firestore API to Add, Update, Delete and Query Documents

To interact with Firestore database, you need to get instance of FirebaseFirestore class by calling getInstance static method of FirebaseFirestore. To add a collection or get reference to collection, you need to call collection method specifying collection name on FirebaseFirestore object. The method returns CollectionReference using that you can add documents to the collection. To get reference to a document, you can use document method specifying document path.

CollectionReference class extends Query, so using CollectionReference not only you can add documents but you can query the collection to get matching documents.

You can add, edit, delete documents using Firebase console also.

I’ll show how to use Firestore in Android using events app example. The example uses fragments for add, edit and update event screen and displays list of events in RecyclerView. Add and view events functionality can be accessed using Toolbar menu. Edit and delete events functionality can be accessed from view events screen.

Add Document to Firestore Database

firebase firestore add document android example

To add a document, first you need to name the collection using collection method of FirebaseFirestore object and then you can add document to it using add method on the resulting CollectionReference object. You can use Map or custom data model POJO object to add document to collection.

The add method of CollectionReference object returns Task to that you can add OnSuccessListener to know whether the document has been added to Firestore or not.

        firestoreDB.collection("events")
                .add(event)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        restUi();
                        Toast.makeText(getActivity(),
                                "Event document has been added",
                                Toast.LENGTH_SHORT).show();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "Error adding event document", e);
                        Toast.makeText(getActivity(),
                                "Event document could not be added",
                                Toast.LENGTH_SHORT).show();
                    }
                }); 

In the above example, Firestore automatically generates id and adds it to the document. If you want to use custom document id instead of Firestore generated one, you need to add empty document specifying id using document method of CollectionReference object. Then you can use the resulting DocumentReference object to the set the data using set method and passing map or pojo object to it.

Query FireStore Database

firebase firestore query android example

To get document by document id, first you need to get DocumentReference object using document method of CollectionReference object passing document id and then on the resulting DocumentReference object call get method that will return DocumentSnapshot object. DocumentSnapshot has various get methods to get individual field’s data. You can convert document to pojo or custom object using toObject method. You can get metadata using getMetadata method which returns SnapshotMetadata object.

To get list of documents that have specified value for a field, you need to use whereEqualTo method of CollectionReference object passing field name and value, then on the resulting Query object, call get method which will return QuerySnapshot. Other conditional methods inherited from Query of CollectionReference are whereGreaterThan, whereGreaterThanOrEqualTo, whereLessThan and whereLessThanOrEqualTo.

You can limit the documents using limit method of Query object and also you can order the results by using orderBy methods.

You can convert list of documents into list of pojo or custom object using toObject method of QuerySnapshot. You can get List of DocumentSnapshot objects from QuerySnapshot using getDocuments method. Method toObject doesn’t populate document id, so if you need document id, you need to get it from DocumentSnapshot by calling getId method.

Below is our example app screen shot that shows list of events in recycler view.

firebase firestore view list of documents android recycler view example
      firestoreDB.collection("events")
                .whereEqualTo("type", eventType)
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                           List<Event> eventList = new ArrayList<>();

                           for(DocumentSnapshot doc : task.getResult()){
                              Event e = doc.toObject(Event.class);
                              e.setId(doc.getId());
                               eventList.add(e);
                           }
			   //do something with list of pojos retrieved

                        } else {
                            Log.d(TAG, "Error getting documents: ", task.getException());
                        }
                    }
                }); 

To receive data change events, instead of calling get methods, you need to call addSnapshotListener.This way, firestore will call listener every time there is a data change.

 firestoreDB.collection("events")
        .whereEqualTo("type", eventType)
        .addSnapshotListener(getActivity(), new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
                for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
                    doc.getDocument().toObject(Event.class);
                    //do something...
                }
            }
        });

Update Document in FireStore Database

To update a document, you need to first get DocumentReference and set data using map or pojo. You can use SetOptions object to merge updates instead of overwriting document. You can also use update method of DocumentReference to update fields of the document referred to by the DocumentReference. The difference between set and update methods of DocumentReference is that set creates a document if document doesn’t exist yet where as update will fail.

firebase firestore update document android example
       firestoreDB.collection("events")
                .document(docId)
                .set(event, SetOptions.merge())
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
		}}); 

Delete Document from FireStore Database

To delete document, first get DocumentReference object using document method of CollectionReference object passing document id and then call delete method on DocumentReference.

        firestoreDB.collection("events").document(docId).delete()
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {                       
                        Toast.makeText(context,
                                "Event document has been deleted",
                                Toast.LENGTH_SHORT).show();
                    }
                }); 

To delete fields, you need to use Map adding field names and value as FieldValue.delete() and pass the map to update method of DocumentReference object.

Firestore Android Example

Activity

 import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public class EventActivity extends AppCompatActivity {

    private FragmentManager fm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.event_layout);

        Toolbar tb = findViewById(R.id.toolbar);
        setSupportActionBar(tb);
        tb.setSubtitle("Firestore");

        fm = getSupportFragmentManager();
        addEventFrgmt();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.add_event_m:
                addEventFrgmt();
                return true;
            case R.id.view_events_m:
                viewEventsFrgmt();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    public void addEventFrgmt(){
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.events_content, new AddEventFragment());
        ft.commit();
    }
    public void viewEventsFrgmt(){
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.events_content, new ViewEventsFragment());
        ft.commit();
    }
}

Activity layout

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".EventActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <FrameLayout
        android:id="@+id/events_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"/>
</android.support.constraint.ConstraintLayout>

Add document fragment

 import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.SetOptions;

import zoftino.com.firestore.model.Event;

public class AddEventFragment extends Fragment {

    private static final String TAG = "AddEventFragment";

    private FirebaseFirestore firestoreDB;
    private boolean isEdit;

    private String docId;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.add_event,
                container, false);

        Button button = (Button) view.findViewById(R.id.add_event);

        Event  event = null;
        if(getArguments() != null){
            event = getArguments().getParcelable("event");
            ((TextView)view.findViewById(R.id.add_tv)).setText("Edit Event");
        }
        if(event != null){
            ((TextView) view.findViewById(R.id.event_name_a)).setText(event.getName());
            ((TextView) view.findViewById(R.id.event_type_a)).setText(event.getType());
            ((TextView) view.findViewById(R.id.event_place_a)).setText(event.getPlace());
            ((TextView) view.findViewById(R.id.event_start_time_a)).setText(event.getStartTime());
            ((TextView) view.findViewById(R.id.event_end_time_a)).setText(event.getEndTime());

            button.setText("Edit Event");
            isEdit = true;
            docId = event.getId();
        }

        firestoreDB = FirebaseFirestore.getInstance();


        button.setOnClickListener(new View.OnClickListener()        {
            @Override
            public void onClick(View v)
            {
                if(!isEdit){
                    addEvent();
                }else {
                    updateEvent();
                }

            }
        });

        return view;
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }
    public void addEvent(){
        Event event = createEventObj();
        addDocumentToCollection(event);
    }
    public void updateEvent(){
        Event event = createEventObj();
        updateDocumentToCollection(event);
    }
    private Event createEventObj(){
        final Event event = new Event();
        event.setName(((TextView)getActivity()
                .findViewById(R.id.event_name_a)).getText().toString());
        event.setPlace(((TextView)getActivity()
                .findViewById(R.id.event_place_a)).getText().toString());
        event.setType(((TextView)getActivity()
                .findViewById(R.id.event_type_a)).getText().toString());
        event.setStartTime(((TextView)getActivity()
                .findViewById(R.id.event_start_time_a)).getText().toString());
        event.setEndTime(((TextView)getActivity()
                .findViewById(R.id.event_end_time_a)).getText().toString());

        return event;
    }
    private void addDocumentToCollection(Event event){
        firestoreDB.collection("events")
                .add(event)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        Log.d(TAG, "Event document added - id: "
                                + documentReference.getId());
                        restUi();
                        Toast.makeText(getActivity(),
                                "Event document has been added",
                                Toast.LENGTH_SHORT).show();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "Error adding event document", e);
                        Toast.makeText(getActivity(),
                                "Event document could not be added",
                                Toast.LENGTH_SHORT).show();
                    }
                });
    }
    private void updateDocumentToCollection(Event event){
        firestoreDB.collection("events")
                .document(docId)
                .set(event, SetOptions.merge())
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.d(TAG, "Event document updated ");
                        Toast.makeText(getActivity(),
                                "Event document has been updated",
                                Toast.LENGTH_SHORT).show();
                        showEventScreen();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "Error adding event document", e);
                        Toast.makeText(getActivity(),
                                "Event document could not be added",
                                Toast.LENGTH_SHORT).show();
                    }
                });
    }
    private void restUi(){
        ((TextView)getActivity()
                .findViewById(R.id.event_name_a)).setText("");
        ((TextView)getActivity()
                .findViewById(R.id.event_type_a)).setText("");
        ((TextView)getActivity()
                .findViewById(R.id.event_place_a)).setText("");
        ((TextView)getActivity()
                .findViewById(R.id.event_start_time_a)).setText("");
        ((TextView)getActivity()
                .findViewById(R.id.event_end_time_a)).setText("");
    }
    private void showEventScreen() {
        Intent i = new Intent();
        i.setClass(getActivity(), EventActivity.class);
        startActivity(i);
    }
}

Add fragment layout

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".EventActivity">
    <TextView
        android:id="@+id/add_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:text="Add Event"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"  />
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_name_la"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/add_tv">
        <EditText
            android:id="@+id/event_name_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event name"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_type_la"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/event_name_la">
        <EditText
            android:id="@+id/event_type_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event type"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_place_la"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/event_type_la">
        <EditText
            android:id="@+id/event_place_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event place"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_start_time_la"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/event_place_la">
        <EditText
            android:id="@+id/event_start_time_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event start time"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_end_time_la"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/event_start_time_la">
        <EditText
            android:id="@+id/event_end_time_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event end time"/>
    </android.support.design.widget.TextInputLayout>
    <Button
        android:id="@+id/add_event"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Widget.AppCompat.Button.Colored"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/event_end_time_la"
        android:text="Add Events"/>
</android.support.constraint.ConstraintLayout>

View documents fragment

 import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.List;

import zoftino.com.firestore.model.Event;

public class ViewEventsFragment extends Fragment {
    private static final String TAG = "ViewEventsFragment";
    private FirebaseFirestore firestoreDB;
    private RecyclerView eventsRecyclerView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.view_events,
                container, false);

        firestoreDB = FirebaseFirestore.getInstance();

        Button button = (Button) view.findViewById(R.id.view_event);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewEvents();
            }
        });

        eventsRecyclerView = (RecyclerView) view.findViewById(R.id.events_lst);

        LinearLayoutManager recyclerLayoutManager =
                new LinearLayoutManager(getActivity().getApplicationContext());
        eventsRecyclerView.setLayoutManager(recyclerLayoutManager);

        DividerItemDecoration dividerItemDecoration =
                new DividerItemDecoration(eventsRecyclerView.getContext(),
                        recyclerLayoutManager.getOrientation());
        eventsRecyclerView.addItemDecoration(dividerItemDecoration);

        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    public void viewEvents() {
        String eventType = ((TextView) getActivity()
                .findViewById(R.id.event_type_v)).getText().toString();
        getDocumentsFromCollection(eventType);
    }

    private void getDocumentsFromCollection(String eventType) {
        firestoreDB.collection("events")
                .whereEqualTo("type", eventType)
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                           List<Event> eventList = new ArrayList<>();

                           for(DocumentSnapshot doc : task.getResult()){
                              Event e = doc.toObject(Event.class);
                              e.setId(doc.getId());
                               eventList.add(e);
                           }
                            EventsRecyclerViewAdapter recyclerViewAdapter = new
                                    EventsRecyclerViewAdapter(eventList,
                                    getActivity(), firestoreDB);
                            eventsRecyclerView.setAdapter(recyclerViewAdapter);

                        } else {
                            Log.d(TAG, "Error getting documents: ", task.getException());
                        }
                    }
                });

        firestoreDB.collection("events")
                .whereEqualTo("type", eventType)
                .addSnapshotListener(getActivity(), new EventListener<QuerySnapshot>() {
                    @Override
                    public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
                        for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
                            doc.getDocument().toObject(Event.class);
                            //do something...
                        }
                    }
                });
    }
}

View fragment layout

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".EventActivity">
    <TextView
        android:id="@+id/view_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        android:text="View Events"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"  />
    <android.support.design.widget.TextInputLayout
        android:id="@+id/event_type_lv"
        android:layout_marginTop="4dp"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/view_event"
        app:layout_constraintTop_toBottomOf="@+id/view_tv">
        <EditText
            android:id="@+id/event_type_v"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Event type"/>
    </android.support.design.widget.TextInputLayout>
    <Button
        android:id="@+id/view_event"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        style="@style/Widget.AppCompat.Button.Colored"
        app:layout_constraintLeft_toRightOf="@+id/event_type_lv"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_tv"
        android:text="View Events"/>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/events_lst"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_event"/>
</android.support.constraint.ConstraintLayout>

Document list recycler view adapter

 public class EventsRecyclerViewAdapter extends
        RecyclerView.Adapter<EventsRecyclerViewAdapter.ViewHolder> {

    private List<Event> eventsList;
    private Context context;
    private FirebaseFirestore firestoreDB;

    public EventsRecyclerViewAdapter(List<Event> list, Context ctx, FirebaseFirestore firestore) {
        eventsList = list;
        context = ctx;
        firestoreDB = firestore;
    }
    @Override
    public int getItemCount() {
        return eventsList.size();
    }

    @Override
    public EventsRecyclerViewAdapter.ViewHolder
    onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.view_event_item, parent, false);

        EventsRecyclerViewAdapter.ViewHolder viewHolder =
                new EventsRecyclerViewAdapter.ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(EventsRecyclerViewAdapter.ViewHolder holder, int position) {
        final int itemPos = position;
        final Event event = eventsList.get(position);
        holder.name.setText(event.getName());
        holder.place.setText(event.getPlace());
        holder.startTime.setText("" + event.getStartTime());

        holder.edit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                editEventFragment(event);
            }
        });

        holder.delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                deleteEvent(event.getId(), itemPos);
            }
        });
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public TextView name;
        public TextView place;
        public TextView startTime;

        public Button edit;
        public Button delete;

        public ViewHolder(View view) {
            super(view);

            name = (TextView) view.findViewById(R.id.name_tv);
            place = (TextView) view.findViewById(R.id.place_tv);
            startTime = (TextView) view.findViewById(R.id.start_time_tv);

            edit = view.findViewById(R.id.edit_event_b);
            delete = view.findViewById(R.id.delete_event_b);
        }
    }

   private void editEventFragment(Event event){
       FragmentManager fm = ((EventActivity)context).getSupportFragmentManager();

       Bundle bundle=new Bundle();
       bundle.putParcelable("event", event);

       AddEventFragment addFragment = new AddEventFragment();
       addFragment.setArguments(bundle);

       fm.beginTransaction().replace(R.id.events_content, addFragment).commit();
   }
    private void deleteEvent(String docId, final int position){
        firestoreDB.collection("events").document(docId).delete()
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        eventsList.remove(position);
                        notifyItemRemoved(position);
                        notifyItemRangeChanged(position, eventsList.size());
                        Toast.makeText(context,
                                "Event document has been deleted",
                                Toast.LENGTH_SHORT).show();
                    }
                });
    }
}

Recycler view item layout

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".EventActivity">
    <TextView
        android:id="@+id/name_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/place_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/name_tv" />
    <TextView
        android:id="@+id/start_time_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/place_tv" />
    <Button
        android:id="@+id/edit_event_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="0dp"
        android:minWidth="0dp"
        style="@style/Widget.AppCompat.Button.Colored"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/delete_event_b"
        app:layout_constraintTop_toBottomOf="@+id/start_time_tv"
        android:text="Edit"/>
    <Button
        android:id="@+id/delete_event_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="0dp"
        android:minWidth="0dp"
        style="@style/Widget.AppCompat.Button.Colored"
        app:layout_constraintLeft_toRightOf="@+id/edit_event_b"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/start_time_tv"
        android:text="Delete"/>
</android.support.constraint.ConstraintLayout>