Android Firebase : GridView Master Detail

Android RSS : GridView Multiple Fields – Downlaod,Parse,Show Headlines
Java MySQL Database Template
IDG Contributor Network: The top 5 Java 8 features for developers

Android Firebase : GridView Master Detail







Android Firebase GridView Master Detail  Tutorial.

The Plan

This is an android firebase gridview tutorial. How to save data to firebase,retrieve then show that data in a custom gridview.

  • Save data from edittext to google firebase database.
  • Retrieve the data by attaching events to a DatabaseReference instance.
  • Bind the data to a csutom gridview using a BaseAdapter subclass.
  • Handle the GridView's itemClicks.
  • Open new Activity when a grid item is clicked.
  • Pass data to that new activity

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.

Video Tutorial  For Demo,Firebase setup as well as more Explanations please check our video tutorial here : [embedyt] http://www.youtube.com/watch?v=M6jimzL-1LI[/embedyt]

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.firebasegridviewmdetail.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 spacecraft objects.
package com.tutorials.hp.firebasegridviewmdetail.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.firebasegridviewmdetail.m_Model.Spacecraft;
import java.util.ArrayList;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1.SAVE DATA TO FIREBASE
 * 2. RETRIEVE
 * 3.RETURN AN ARRAYLIST
 */
public class FirebaseHelper {
    DatabaseReference db;
    Boolean saved=null;
    ArrayList<Spacecraft> spacecrafts=new ArrayList<>();
    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 CustomAdapter class

  • Responsible for Layout Inflation.
  • Also for data binding to views.
  • Then opens new activity and passes data to it via android.Content.Intent.
package com.tutorials.hp.firebasegridviewmdetail.m_UI;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.tutorials.hp.firebasegridviewmdetail.DetailActivity;
import com.tutorials.hp.firebasegridviewmdetail.R;
import com.tutorials.hp.firebasegridviewmdetail.m_Model.Spacecraft;
import java.util.ArrayList;
/**
 * Created by Oclemy on 6/21/2016 for ProgrammingWizards Channel and http://www.camposha.com.
 * 1. where WE INFLATE OUR MODEL LAYOUT INTO VIEW ITEM
 * 2. THEN BIND DATA
 */
public class CustomAdapter extends BaseAdapter {
    Context c;
    ArrayList<Spacecraft> spacecrafts;
    public CustomAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
        this.c = c;
        this.spacecrafts = spacecrafts;
    }
    @Override
    public int getCount() {
        return spacecrafts.size();
    }
    @Override
    public Object getItem(int position) {
        return spacecrafts.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView==null)
        {
            convertView= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
        }
        TextView nameTxt= (TextView) convertView.findViewById(R.id.nameTxt);
        TextView propTxt= (TextView) convertView.findViewById(R.id.propellantTxt);
        TextView descTxt= (TextView) convertView.findViewById(R.id.descTxt);
        final Spacecraft s= (Spacecraft) this.getItem(position);
        nameTxt.setText(s.getName());
        propTxt.setText(s.getPropellant());
        descTxt.setText(s.getDescription());
        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //OPEN DETAIL
                openDetailActivity(s.getName(),s.getDescription(),s.getPropellant());
            }
        });
        return convertView;
    }
    //OPEN DETAIL ACTIVITY
    private void openDetailActivity(String...details)
    {
        Intent i=new Intent(c,DetailActivity.class);
        i.putExtra("NAME_KEY",details[0]);
        i.putExtra("DESC_KEY",details[1]);
        i.putExtra("PROP_KEY",details[2]);
        c.startActivity(i);
    }
}

Section 4 : Our MainActivity

  • Launcher activity.
  • Reference GridView set its adapter.
  • Shows Input Dialog on FAB button click.
  • Sets up our Firebase's by initializing the DatabaseReference.
package com.tutorials.hp.firebasegridviewmdetail;
import android.app.Dialog;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.Toast;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.tutorials.hp.firebasegridviewmdetail.m_FireBase.FirebaseHelper;
import com.tutorials.hp.firebasegridviewmdetail.m_Model.Spacecraft;
import com.tutorials.hp.firebasegridviewmdetail.m_UI.CustomAdapter;
/*
1.INITIALIZE FIREBASE DB
2.INITIALIZE UI
3.DATA INPUT
 */
public class MainActivity extends AppCompatActivity {
    DatabaseReference db;
    FirebaseHelper helper;
    CustomAdapter adapter;
    GridView gv;
    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);
        gv= (GridView) findViewById(R.id.gv);
        //INITIALIZE FIREBASE DB
        db= FirebaseDatabase.getInstance().getReference();
        helper=new FirebaseHelper(db);
        //ADAPTER
        adapter=new CustomAdapter(this,helper.retrieve());
        gv.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()
    {
        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);
                //SIMPLE VALIDATION
                if(name != null && name.length()>0)
                {
                    //THEN SAVE
                    if(helper.save(s))
                    {
                        //IF SAVED CLEAR EDITXT
                        nameEditTxt.setText("");
                        propTxt.setText("");
                        descTxt.setText("");
                        adapter=new CustomAdapter(MainActivity.this,helper.retrieve());
                        gv.setAdapter(adapter);
                    }
                }else
                {
                    Toast.makeText(MainActivity.this, "Name Must Not Be Empty", Toast.LENGTH_SHORT).show();
                }
            }
        });
        d.show();
    }
}

Section 4 : Our DetailActivity

  • Yes,the detail activity here.To show our details.
  • Receives data from MainActivity via Intent.
  • Shows the data in TextViews.
package com.tutorials.hp.firebasegridviewmdetail;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;
public class DetailActivity extends AppCompatActivity {
    TextView nameTxt,descTxt, propTxt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        nameTxt = (TextView) findViewById(R.id.nameDetailTxt);
        descTxt= (TextView) findViewById(R.id.descDetailTxt);
        propTxt = (TextView) findViewById(R.id.propellantDetailTxt);
        //get intent
        Intent i=this.getIntent();
        //RECEIVE DATA
        String name=i.getExtras().getString("NAME_KEY");
        String desc=i.getExtras().getString("DESC_KEY");
        String propellant=i.getExtras().getString("PROP_KEY");
        //BIND DATA
        nameTxt.setText(name);
        descTxt.setText(desc);
        propTxt.setText(propellant);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }
}

Section 6 : Our Layouts

ActivityMain.xml

  • Contains our ContentMain.xml
  • Template layout

ContentMain.xml

  • Our Master View
  • Contains our GridView

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

  • defines our custom grids.
  • Available In Source.

ContentDetail.xml

  • Our Detail View.
  • Please view the source.

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.firebasegridviewmdetail">
    <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>
        <activity
            android:name=".DetailActivity"
            android:label="@string/title_activity_detail"
            android:theme="@style/AppTheme.NoActionBar"></activity>
    </application>
</manifest>
  • To setup Firebase properly please check our video tutorial.

Our Result

Save To Firebase

Save To Firebase From Dialog

detail page

Detail Page

Cheers.



    Leave a Reply

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

    seventeen − 14 =

    COMMENTS