Android Firebase : RecyclerView Multiple Fields

Android Firebase : RecyclerView Multiple Fields







Android Firebase Database RecyclerView Tutorial

The Plan

This is an android firebase database RecyclerView tutorial.

How to save data to firebase,retrieve then show that data in a custom RecyclerView.

  • Save data from edittext to google firebase database.
  • Retrieve the data by attaching events to a DatabaseReference instance.
  • Bind the data to a custom GridView using RecyclerView.Adapter Subclass.
  • Our RecyclerView has custom CardViews with several fields.

What Is Firebase Realtime Database?

Firebase Realtime database is a database backend as a service Cloud hosted solution that gives us the platform to build rich apps.Normally we are used to making HTTP requests to read or write data against our servers.But not in Firebase.It uses synchronization technology that allows it to be realtime,but still performant.

Main Feautures?

  • Its realtime .
  • Platfrom Independent.
  • Easy Access Control.
  • It’s a NoSQL solution and is heavily optimized for performance.
  • Has Offline capability .
  • Its User Friendly.

 

The Main Points

Section 1 : Our Model Class

  • Is our Data Object class
  • Must Have an empty constructor.
  • You can create,pass data to and use other constructors
package com.tutorials.hp.firebaserecyclermulti_items.m_Model;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1. OUR MODEL CLASS
 */
public class Spacecraft {
    String name,propellant,description;
    public Spacecraft() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPropellant() {
        return propellant;
    }
    public void setPropellant(String propellant) {
        this.propellant = propellant;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
}

Section 2 : Our FirebaseHelper Class

  • Basically,our CRUD class.
  • Here we perform reads and writes to Firebase database.
  • To persist data we use setValue().
  • Prior to calling setValue() method,we call push() to ensure we append data to database,not replace.
  • We fill an arraylist with model objects.
package com.tutorials.hp.firebaserecyclermulti_items.m_FireBase;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.DatabaseReference;
import com.tutorials.hp.firebaserecyclermulti_items.m_Model.Spacecraft;
import java.util.ArrayList;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1. RECEIVE DB REFERENCE
 * 2. SAVE
 * 3. RETRIEVE
 * 4. RETURN ARRAYLIST
 */
public class FirebaseHelper {
    DatabaseReference db;
    Boolean saved=null;
    ArrayList<Spacecraft> spacecrafts=new ArrayList<>();
    /*
     PASS DATABASE REFRENCE
 */
    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }
    //WRITE IF NOT NULL
    public Boolean save(Spacecraft spacecraft)
    {
        if(spacecraft==null)
        {
            saved=false;
        }else
        {
            try
            {
                db.child("Spacecraft").push().setValue(spacecraft);
                saved=true;
            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved=false;
            }
        }
        return saved;
    }
    //IMPLEMENT FETCH DATA AND FILL ARRAYLIST
    private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();
        for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            Spacecraft spacecraft=ds.getValue(Spacecraft.class);
            spacecrafts.add(spacecraft);
        }
    }
    //READ BY HOOKING ONTO DATABASE OPERATION CALLBACKS
    public ArrayList<Spacecraft> retrieve()
    {
        db.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot);
            }
            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot);
            }
            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
            }
            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
        return spacecrafts;
    }
}

Section 3 : Our ViewHolder class

  • Holds the views for us to recycle.
  • Subclasses RecyclerView.ViewHolder
package com.tutorials.hp.firebaserecyclermulti_items.m_UI;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.tutorials.hp.firebaserecyclermulti_items.R;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1. HOLD VIEWS
 */
public class MyViewHolder extends RecyclerView.ViewHolder {
    TextView nameTxt,propTxt,descTxt;
    public MyViewHolder(View itemView) {
        super(itemView);
        nameTxt=(TextView) itemView.findViewById(R.id.nameTxt);
        propTxt=(TextView) itemView.findViewById(R.id.propellantTxt);
        descTxt=(TextView) itemView.findViewById(R.id.descTxt);
    }
}

Section 4 : Our MyAdapter class

  • Responsible for Layout Inflation.
  • Also for data binding to views.
  • This class subclasses RecyclerView.Adapter<ViewHolder>
package com.tutorials.hp.firebaserecyclermulti_items.m_UI;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorials.hp.firebaserecyclermulti_items.R;
import com.tutorials.hp.firebaserecyclermulti_items.m_Model.Spacecraft;
import java.util.ArrayList;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1. LAYOUT INFLATION
 * 2. RECEIVE SPACECRAFTS
 * 3. PERFORM BINDING
 */
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    Context c;
    ArrayList<Spacecraft> spacecrafts;
    public MyAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
        this.c = c;
        this.spacecrafts = spacecrafts;
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v=LayoutInflater.from(c).inflate(R.layout.model,parent,false);
        return new MyViewHolder(v);
    }
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.nameTxt.setText(spacecrafts.get(position).getName());
        holder.propTxt.setText(spacecrafts.get(position).getPropellant());
        holder.descTxt.setText(spacecrafts.get(position).getDescription());
    }
    @Override
    public int getItemCount() {
        return spacecrafts.size();
    }
}

Section 5 : Our MainActivity

  • Launcher activity.
  • Reference RecyclerView and set its LayoutManager
  • Set its adapter.
  • Shows Input Dialog on FAB button click.
  • Sets up our Firebase's by initializing the DatabaseReference.
package com.tutorials.hp.firebaserecyclermulti_items;
import android.app.Dialog;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.tutorials.hp.firebaserecyclermulti_items.m_FireBase.FirebaseHelper;
import com.tutorials.hp.firebaserecyclermulti_items.m_Model.Spacecraft;
import com.tutorials.hp.firebaserecyclermulti_items.m_UI.MyAdapter;
/*
1.INITIALIZE FIREBASE DB
2.INITIALIZE UI
3.DATA*/
public class MainActivity extends AppCompatActivity {
    DatabaseReference db;
    FirebaseHelper helper;
    MyAdapter adapter;
    RecyclerView rv;
    EditText nameEditTxt,propTxt,descTxt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //INITIALIZE RV
        rv= (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        //INITIALIZE FB
        db= FirebaseDatabase.getInstance().getReference();
        helper=new FirebaseHelper(db);
        //ADAPTER
        adapter=new MyAdapter(this,helper.retrieve());
        rv.setAdapter(adapter);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                displayInputDialog();
            }
        });
    }
    //DISPLAY INPUT DIALOG
    private void displayInputDialog()
    {
        //CREATE DIALOG
        Dialog d=new Dialog(this);
        d.setTitle("Save To Firebase");
        d.setContentView(R.layout.input_dialog);
        nameEditTxt= (EditText) d.findViewById(R.id.nameEditText);
        propTxt= (EditText) d.findViewById(R.id.propellantEditText);
        descTxt= (EditText) d.findViewById(R.id.descEditText);
        Button saveBtn= (Button) d.findViewById(R.id.saveBtn);
        //SAVE
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //GET DATA
                String name=nameEditTxt.getText().toString();
                String propellant=propTxt.getText().toString();
                String desc=descTxt.getText().toString();
                //SET DATA
                Spacecraft s=new Spacecraft();
                s.setName(name);
                s.setPropellant(propellant);
                s.setDescription(desc);
                //SAVE
                if(name != null && name.length()>0)
                {
                    if(helper.save(s))
                    {
                        nameEditTxt.setText("");
                        propTxt.setText("");
                        descTxt.setText("");
                        adapter=new MyAdapter(MainActivity.this,helper.retrieve());
                        rv.setAdapter(adapter);
                    }
                }else
                {
                    Toast.makeText(MainActivity.this, "Name Must Not Be Empty", Toast.LENGTH_SHORT).show();
                }
            }
        });
        d.show();
    }
}

Section 6 : Our Layouts

InputDialog.xml

  • defines our input dialogs layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="?attr/actionBarSize"
        android:orientation="vertical"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:paddingTop="50dp">
        <android.support.design.widget.TextInputLayout
            android:id="@+id/nameLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:id="@+id/nameEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:hint= "Name" />
        </android.support.design.widget.TextInputLayout>
        <android.support.design.widget.TextInputLayout
            android:id="@+id/propLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:id="@+id/propellantEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:hint= "Propellant" />
        <android.support.design.widget.TextInputLayout
            android:id="@+id/descLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:id="@+id/descEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:hint= "Description" />
        </android.support.design.widget.TextInputLayout>
        </android.support.design.widget.TextInputLayout>
        <Button android:id="@+id/saveBtn"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Save"
            android:clickable="true"
            android:background="@color/colorAccent"
            android:layout_marginTop="40dp"
            android:textColor="@android:color/white"/>
    </LinearLayout>
</LinearLayout>

Model.xml

  • How each view item shall appear.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="5dp"
    card_view:cardElevation="5dp"
    android:layout_height="200dp">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text="Name"
                android:id="@+id/nameTxt"
                android:padding="10dp"
                android:textColor="@color/colorAccent"
                android:textStyle="bold"
                android:layout_alignParentLeft="true"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text="Description....................."
                android:lines="3"
                android:id="@+id/descTxt"
                android:padding="10dp"
                android:layout_alignParentLeft="true"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="Propellant"
                android:textStyle="italic"
                android:id="@+id/propellantTxt" />
    </LinearLayout>
</android.support.v7.widget.CardView>

Section 7 : Reminders

  • Remember to add permission for internet in your manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tutorials.hp.firebaserecyclermulti_items">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
  • To setup Firebase properly please check our video tutorial.

 

Cheers.



Leave a Reply

Your email address will not be published. Required fields are marked *

twelve + twenty =

COMMENTS