Android Firebase Realtime Database with RecyclerView チュートリアル_」です。

今回は、RecyclerViewとFirebase Realtimeデータベースの例をいくつか見ていきたいと思います。基本的には、RecyclerViewで追加、取得、表示などのCRUD操作を行う方法です。

Firebase Realtime Database とは?

Firebase Realtime Database は、Google が所有する Firebase Platform が提供するサービスの一つです。

基本的にはデータベースBAASと呼ばれるもので、Database Backend As A Serviceと呼ばれるものです。クラウドで提供されています。

なぜFirebase Realtime Databaseなのか?

Firebase Realtime Databaseは、多くのデータベースと異なる点があります。Firebase Realtime Databaseの利点は以下の通りです。

  1. SQLiteやRealmはローカルにホストされていますが、Firebaseはクラウドにホストされています。そのため、Firebase Realtime Databaseは多くのアプリからアクセスすることができます。SQLiteやRealmのようなデータベースは、1つのアプリの中でローカライズされています。Firebase Realtime Databaseは、多くのアプリケーションからアクセスできます。
    1. リアルタイムであること。これが一番大きな違いです。つまり、データを保存すると、自動的に接続されているすべてのアプリのデータが瞬時に更新されます。そのため、チャットやメッセージングアプリ、即時同期が必要なアプリなど、様々なタイプのアプリに適用できます。
    1. データは、sqliteのテーブルとは異なり、json形式で保存されます。このため、Firebase Realtime Databaseは非常にスケーラブルである。
    1. 無料と有料のプランがあります。無料版と有料版があり、学習用と商用を使い分けることができます。

RecyclerViewとは?

RecyclerViewは、大きなデータセットを効率的にレンダリングすることができるandroidのアダプタービューです。通常、androidでリストデータをレンダリングするには、adapterviewとadapterが必要です。adapterviewはリストウィジェットで、例としては ListView, Gridview, Spinner, そしてもちろんRecyclerViewが挙げられます。

そして、アダプタは通常、アダプタビューをデータソースに接続する役割を担います。そして、実際には通常、カスタムレイアウトを使用して、単一のリストアイテムを表示することができます。そのレイアウトもアダプタの内部で膨らませます。

Read more RecyclerViewについてはこちら

なぜRecyclerViewなのか?

アンドロイドでデータを表示するために、いくつかのadapterviewが使えると言いました。ListView、GridView、Spinnerなどです。ListViewは、RecyclerViewが登場するまでは最もポピュラーなものでした。

最近、リサイクルビューは、その柔軟性とパフォーマンスのために、最も一般的に使用されるadapterviewです。RecyclerViewは、リストビュー、グリッド/スタッガードビュー、テーブルビュー、カレンダーなど、ほとんどすべてのタイプのビューを構築するために使用することができます。

この事実が、RecyclerViewを特別なものにしており、多くのシナリオで使用することができます。しかし、他の adapterview と比べても、それほど難しいものではありません。

使用したツール

このサンプルは、以下のツールを使って書かれています。

  • Microsoft Windows 8.1 - これは私のオペレーティング・システムです。
  • Android Studio - Jetbrains と Google による IDE(Integerated Develpment Kit)です。
  • Genymotion Emulator - これは、私たちのアプリケーションをテストするために使用します。
  • 言語:Java - Javaは最も人気のあるプログラミング言語です。

1. Android Firebase => Simple RecyclerView - Save,Retrieve then Show

\୧⃛(๑⃙⃘◡̈๑⃙⃘)୨⃛ Android Firebase Realtime Database recyclerView Tutorial

Android FirebaseのRecyclerViewのチュートリアルです。Firebaseにデータを保存して、そのデータをRecyclerViewで表示する方法です。このチュートリアルでは、1つのフィールドのデータを使用します。

この例から学ぶ一般的な概念。

このチュートリアルで学ぶことのできる概念をいくつか紹介します。

  • Firebaseとは何か、RecyclerViewとは何か、なぜそれらを使用するのか。
  • Google Firebase Realtime Databaseにedittextからデータを保存する方法。
  • Firebase のデータベースからデータを取得、読み込み、取得する方法です。
  • 取得したデータを RecyclerView.Adapter サブクラスのインスタンスにバインドする方法。
  • Firebaseでデータベースを作成し、操作する方法。
  • リサイクルビューを使ったFirebaseのサンプルアプリ。
  • Firebaseのデータベース同期

学習する具体的な概念

  • Firebase Database Referenceの使い方
  • Firebase Database Referenceに子を追加する方法。

デモ

このチュートリアルのプロジェクトのデモはこちらです。

セットアップと設定

(a). 基本的なActivityプロジェクトの作成
  1. まず、android studioで新しいプロジェクトを作成します。
(b). Firebaseの作成と設定ファイルのダウンロード

Firebase Consoleにアクセスし、Firebaseアプリを作成、アプリIDを登録し、google-services.json`ファイルをダウンロードします。アプリのフォルダに追加します。

(c). Maven リポジトリの URL を指定する

プロジェクトレベル(プロジェクトフォルダ)の build.gradle に移動し、以下の作業を行います。

  1. Googleサービスのクラスパスを以下のように追加します。
  2. mavenのリポジトリURLを追加

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.google.gms:google-services:3.1.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com" // Google's Maven repository
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

これで、Firebaseをmaven.google comから取得することができます。Firebaseはサードパーティのライブラリなので、プロジェクトで使用するためにはダウンロードする必要があります。

(d). Firebaseの依存関係を追加する

アプリレベル(appフォルダ)のbuild.gradleに、いくつかの依存関係を追加する必要があります。今回は、appcompatdesigncardviewといったサポートライブラリを追加しました。AppCompat は AppCompatActivity を提供します。これは MainActivity を派生させるためのクラスです。これらのクラスは implementation ステートメントを使って追加します。

design サポートは、リストウィジェットである recyclerveiew を提供します。これはリストウィジェットで、Firebase からクエリしたデータを取り込むことができます。一方、 cardview` はカードビューをアイテムビューとして扱うことを可能にします。recyclerviewはcardviewで構成されます。

次に、Firebase CoreとFirebase Databaseを追加した。Firebase Core はプラットフォームで、Firebase Database はデータを保存するデータベースです。Firebase Coreはプラットフォーム、Firebase Databaseはデータを保存するデータベースです。ただし、今回のようにgoogleのサービスを適用することを忘れないでください。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:23.3.0'
    implementation 'com.android.support:design:23.3.0'
    implementation 'com.android.support:cardview-v7:23.3.0'

    implementation 'com.google.firebase:firebase-core:11.8.0'
    implementation 'com.google.firebase:firebase-database:11.8.0'
}
apply plugin: 'com.google.gms.google-services'

プラグインを適用してください。com.google.gms.google-services'` を上記のように適用してください。

2. Javaコード

このサンプルは、Javaプログラミング言語を使って書きます。そこで、アプリの様々な部分をいくつかのクラスにデカップリングします。

(a). モデルクラス
  • データオブジェクトのクラスです。
  • 空のコンストラクタを持つ必要があります。
  • 他のコンストラクタを作成したり、データを渡したり、使用することができます。

モデルクラスやデータオブジェクトクラスは、基本的にデータをモデル化するためのクラスです。どのような形式のデータを扱う場合でも、データを具体的でシンプルなクラスで表現するのは良い考えです。そのクラスのオブジェクトは、必要に応じて問い合わせることができます。通常、この種のクラスにはアクセッサメソッドと呼ばれるものがあります。これらのメソッドは常にパブリックであり、常にプライベートであるクラスのプロパティを公開する方法を提供します。

私たちの例では、Spacecraftというクラスを作成しました。このクラスは、宇宙船の名前を格納するためのnameというプロパティを1つ持ちます。そして、このクラスにはパブリックなデフォルトコンストラクタを用意します。これは、データオブジェクトを読み込んでデータベーススキーマを自動的に生成するデータベースエンジンに通常必要とされる機能です。Firebase Databaseは、JavaやandroidのローカルデータベースであるRealmと同様に、間違いなくその機能を備えている。

そして、このクラスには getNamesetName というアクセサメソッドが用意されています。

package com.tutorials.hp.firebasesimplerecyclerview.m_Model;

public class Spacecraft {

    String name;

    //EMPTY CONSTR
    public Spacecraft() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
(b). FirebaseHelperクラス
  • 基本的には、CRUDクラスです。
  • ここでは、Firebaseのデータベースへの読み込みと書き込みを行います。
  • データを保持するために、setValue()を使用します。
  • setValue()メソッドを呼ぶ前に、push()を呼んで、データを置き換えるのではなく、データベースに追加することを保証しています。
  • 単純な配列リストを作成します。

FirebaseHelper クラスは、Firebase からデータを読み込んだり、問い合わせたり、保存したりできるようにするために作成しました。まず、このクラスをホストするパッケージを定義します。そして、 com.google.firebase.database からいくつかのクラスを含むインポートを追加します。

いくつかのインスタンスフィールドを定義しています。

  1. DatabaseReference -- データベースへの参照。
    1. Boolean 値 - 保存に成功したかどうかを判断するためのものです。
  2. ArrayList - Firebase から取得したデータを保持します。

まず、コンストラクタでデータベースリファレンスを受け取ります。そして、そのデータベースリファレンスを、保持しているローカルインスタンスフィールドに代入します。

Saving Data To FirebaseDatabase (データの Firebase データベースへの保存)

次に、Firebase Databaseにデータを保存するためのメソッドを定義します。このメソッドはパラメータとしてSpacecraftオブジェクトを受け取ります。外部からSpacecraftオブジェクトを受け取るので、まずnullであるかどうかをチェックするのが理想的です。

Firebaseにデータを保存する

    db.child("Spacecraft").push().setValue(spacecraft);

この場合、dbDatabaseReference となります。その子ノードを child() メソッドで取得します。次に、"テーブル "の名前を渡します。そして push() メソッドを使用して、Firebase にデータをプッシュします。ただし、プッシュする値を設定する必要があります。setValue メソッドを使用して spacecraft` オブジェクトを設定します。これでFirebase Databaseにデータを保存することができました。データベース例外をキャッチするために try catch ブロックを使用していることに注意してください。

Firebaseデータベースからデータを取得する

Firebase Realtime Databaseからデータを受信し、ArrayListに格納します。そしてそのArrayListをrecyclerviewアダプタのデータソースとして使用します。

Firebase からデータを読み込むには、データベースへの参照に ChildEventListener をアタッチする必要があります。これは、データノードの変更をリスニングするものです。例えば、子ノードが追加、変更、削除、キャンセルされると、データスナップショットを含むコールバックメソッドを取得します。そして、これらのデータスナップショットからデータを読み取ることができる。

そして、各反復からデータスナップショットの子ノードの getValue メソッドを呼び出してオブジェクトを取得することができます。DataSnapshotオブジェクトからデータを読み取るのは簡単です。単純にその子オブジェクトをループさせるだけです。

 for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            String name=ds.getValue(Spacecraft.class).getName();
            spacecrafts.add(name);
        }

以下がそのコードです。

package com.tutorials.hp.firebasesimplerecyclerview.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.firebasesimplerecyclerview.m_Model.Spacecraft;

import java.util.ArrayList;

public class FirebaseHelper {

    DatabaseReference db;
    Boolean saved=null;
    ArrayList<String> spacecrafts=new ArrayList<>();

    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }

    //SAVE
    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;
    }

    //READ
    public ArrayList<String> 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;
    }

    private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();
        for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            String name=ds.getValue(Spacecraft.class).getName();
            spacecrafts.add(name);
        }
    }

}
(c). MyViewHolderクラス
  • はい、これはビューホルダークラスです。
  • リサイクルするために使用するためのビューを保持します。

package com.tutorials.hp.firebasesimplerecyclerview.m_UI;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.tutorials.hp.firebasesimplerecyclerview.R;

public class MyViewHolder extends RecyclerView.ViewHolder  {

    TextView nameTxt;

    public MyViewHolder(View itemView) {
        super(itemView);

        nameTxt=(TextView) itemView.findViewById(R.id.nameTxt);
    }
}

このMyViewHolderは私たちのViewHolderクラスです。これらはリサイクルバービューでビューをリサイクルするために常に必要です。しかし、クラスをリサイクルビューのビューホルダーにするためには、上で見たように Recyclerview.ViewHolder クラスを派生させなければなりません。まず、RecyclerViewを含むいくつかのクラスをインポートすることから始めました。

このクラスでは、nameTxtという名前のTextViewをメンテナンスしています。そして、MyViewHolder構造体はViewオブジェクトを取得しました。そのViewオブジェクトはスーパークラスである Recyclerview.ViewHolder に渡されています。

そして、レイアウト仕様から nameTxt を参照しています。

9. MyAdapterクラス
  • レイアウトの拡張を担当します。
  • また、ビューへのデータバインディングのため。

package com.tutorials.hp.firebasesimplerecyclerview.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.firebasesimplerecyclerview.R;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    Context c;
    ArrayList<String> spacecrafts;

    public MyAdapter(Context c, ArrayList<String> 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));

    }

    @Override
    public int getItemCount() {
        return spacecrafts.size();
    }
}

アダプタは、アンドロイドがデータの収集で動作する方法において重要です。モバイルデバイスは、HTC、Samsung、F7、Apple iOS、Infinixなど、どれもデータのリストをレンダリングする必要があるアプリを多用しています。これは、モバイルデバイスの性質上、仕方のないことです。画面は常に小さいので、スクロールできるアイテムを表示するのが適切です。

そして、RecyclerViewは大きなデータセットを表示するためのナンバーワンアダプタビューです。これらのデータセットは、Firebaseのようなクラウドから来るかもしれません。実際、今回のデータはFirebase Realtimeデータベースから取得しています。ここまでで、収集したデータを ArrayList に格納しました。次はそのデータをバインドします。しかしそのためにはAdapterが必要です。

Adaptersです。

  1. データをアダプタビューにバインドできるようになります。
    1. カスタムレイアウトをビューに展開し、カスタムアダプタビューを設計できるようにする。

リサイクルビューアダプタは、RecyclerView.Adapter<MyViewHolder> から派生して作成します。一般的なパラメータはViewHolderです。このクラスから派生することで、3つのメソッドをオーバーライドすることになります。

    1. getItemCount - リサイクルビューにレンダリングされるアイテムの数を返します。
    1. onCreateViewHolder - ここでインフレが発生します。ここでは、LayoutInflaterを使用してインフレを行います。
    1. onBindViewHolder - ここで、ViewHolderクラスで定義したウィジェットにデータをバインドします。

一方、コンストラクタは、Contextオブジェクトとデータの配列リストを受け取っています。

(d). 私たちのMainActivity
  • Launcherアクティビティです。
  • RecyclerViewを参照し、layoutManagerとadapterを設定します。
  • FABボタンクリックで入力ダイアログを表示します。
  • DatabaseReferenceを初期化し、Firebaseの設定を行います。

package com.tutorials.hp.firebasesimplerecyclerview;

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.firebasesimplerecyclerview.m_FireBase.FirebaseHelper;
import com.tutorials.hp.firebasesimplerecyclerview.m_Model.Spacecraft;
import com.tutorials.hp.firebasesimplerecyclerview.m_UI.MyAdapter;

public class MainActivity extends AppCompatActivity {

    DatabaseReference db;
    FirebaseHelper helper;
    RecyclerView rv;
    EditText nameEditTxt;
    MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //SETUP RV
        rv= (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));

        //SETUP 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();
            }
        });
    }

    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);
        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();

                //SET DATA
                Spacecraft s=new Spacecraft();
                s.setName(name);

                //VALIDATE
                if(name.length()>0 && name != null)
                {
                    if(helper.save(s))
                    {
                        nameEditTxt.setText("");
                         adapter=new MyAdapter(MainActivity.this,helper.retrieve());
                        rv.setAdapter(adapter);
                    }
                }else
                {
                    Toast.makeText(MainActivity.this, "Name Cannot Be Empty", Toast.LENGTH_SHORT).show();
                }
            }
        });

        d.show();
    }

}

11. レイアウト

(a). activity_main.xml

メインのactivityレイアウトです。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_fitsSystemWindows="true"
    tools_context="com.tutorials.hp.firebasesimplerecyclerview.MainActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_gravity="bottom|end"
        android_layout_margin="@dimen/fab_margin"
        android_src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
(b). content_main.xml

ここで、アダプタビュー(この場合はリサイクルバービュー)を追加します。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_paddingBottom="@dimen/activity_vertical_margin"
    android_paddingLeft="@dimen/activity_horizontal_margin"
    android_paddingRight="@dimen/activity_horizontal_margin"
    android_paddingTop="@dimen/activity_vertical_margin"
    app_layout_behavior="@string/appbar_scrolling_view_behavior"
    tools_context="com.tutorials.hp.firebasesimplerecyclerview.MainActivity"
    tools_showIn="@layout/activity_main">

    <android.support.v7.widget.RecyclerView
        android_id="@+id/rv"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
         />
</RelativeLayout>
(c). input_dialog.xml
  • 入力ダイアログのレイアウトを定義します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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="10dp">

        <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>

        <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="10dp"
            android_textColor="@android:color/white"/>

    </LinearLayout>

</LinearLayout>
(d). model.xml

これはRecyclerViewの行モデルです。このレイアウトは、アダプタクラスで展開されます。

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    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"
                />

    </LinearLayout>

</android.support.v7.widget.CardView>
12. AndroidManifest.xml
  • マニフェストファイルでは、インターネットに関するパーミッションを追加することを忘れないでください。

<` とします。

ダウンロード

閲覧
ダウンロード

2. Android Firebase - RecyclerView 複数のフィールドを表示する

Android Firebase Database RecyclerView Tutorial_ これは、Android FirebaseデータベースのRecyclerViewのチュートリアルです。Firebaseにデータを保存して、そのデータをRecyclerViewに表示する方法です。

今回は、前回のように単一フィールドではなく、複数フィールドを使用します。

1. 設定方法

(a). 基本的なアクティビティプロジェクトの作成
  1. まず、android studioで新しいプロジェクトを作成します。File --> New Project を選択します。
(b).Firebaseの作成と設定ファイルのダウンロード

Firebase Consoleにアクセスし、Firebaseアプリを作成、アプリIDを登録し、google-services.json`ファイルをダウンロードします。アプリのフォルダに追加してください。

(c). Maven リポジトリの URL を指定する

プロジェクトレベル(プロジェクトフォルダ)の build.gradle に移動し、以下の作業を行います。

  1. Googleサービスのクラスパスを以下のように追加します。
  2. mavenリポジトリのURLを追加

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.google.gms:google-services:3.1.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com" // Google's Maven repository
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
(d). Firebaseの依存関係の追加

アプリレベル(appフォルダ)内のbuild.gradleに追加します。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'com.android.support:cardview-v7:23.3.0'

    compile 'com.google.firebase:firebase-core:11.8.0'
    compile 'com.google.firebase:firebase-database:11.8.0'
}
apply plugin: 'com.google.gms.google-services'

プラグインを適用してください。'com.google.gms.google-services'` を適用してください。

(e). AndroidManifest
  • マニフェストファイルにインターネットへのアクセス許可を追加することを忘れないでください。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.tutorials.hp.firebaserecyclermulti_items">

    <uses-permission android_name="android.permission.INTERNET"/>
    ....
</manifest>

2. クラス

(a). 私たちのモデルクラス
  • 私たちのデータオブジェクトのクラスです
  • 空のコンストラクタを持つ必要があります。
  • 他のコンストラクタを作成したり、データを渡したり、使用することができます。

package com.tutorials.hp.firebaserecyclermulti_items.m_Model;

/*
 * 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;
    }
}
(b). FirebaseHelperクラス
  • 基本的には、CRUDクラスです。
  • ここでは、Firebaseデータベースへの読み込みと書き込みを行います。
  • データを保持するために、setValue()を使用しています。
  • setValue()メソッドを呼ぶ前に、push()を呼んで、データを置き換えるのではなく、データベースに追加することを保証しています。
  • モデルオブジェクトをarraylistに格納しています。

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;

/*
 * 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;
    }

}
(c). ViewHolderクラス
  • リサイクルするためのビューを保持します。
  • サブクラス 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;

/*
 * 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);
    }
}

9. 私たちのMyAdapterクラス

  • Layout Inflation を担当する。
  • また、ビューへのデータバインディングのため。
  • このクラスはRecyclerView.Adapterをサブクラスとします。

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;

/
 * 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();
    }
}
(d). 私たちのMainActivity
  • Launcherアクティビティです。
  • RecyclerViewを参照し、そのLayoutManagerを設定します。
  • そのアダプタを設定する。
  • FABボタンクリックで入力ダイアログを表示する。
  • DatabaseReferenceを初期化し、Firebaseの設定を行います。

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();
    }
}

3. レイアウト

(a). InputDialog.xml
  • 入力ダイアログのレイアウトを定義します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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>
(b). モデル.xml
  • 各ビューアイテムの表示方法を定義します。

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    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>

4. ダウンロード

ブラウズ
ダウンロード

3. Android Firebase - RecyclerView Master Detail [Open Activity].

こんにちは、Android Firebase RecyclerView Master detail tutorialへようこそ。

このチュートリアルは、Android FirebaseのRecyclerViewのチュートリアルです。このチュートリアルでは、Firebaseにデータを保存して、そのデータをカスタムグリッドビューに表示する方法を説明します。

  • edittextからgoogle firebaseのデータベースにデータを保存します。
  • DatabaseReference インスタンスにイベントをアタッチして、データを取得します。
  • BaseAdapter のサブクラスを使用して、データを csutom グリッドビューにバインドします。
  • GridViewのitemClickを処理する。
  • グリッドアイテムがクリックされたら、新しいアクティビティを開く。
  • その新しいアクティビティにデータを渡す

Firebase Realtime Database とは?

Firebase Realtime Database は、データベースバックエンドとして、リッチなアプリを構築するためのプラットフォームを提供するクラウドホスティングソリューションです。通常、サーバーに対してHTTPリクエストでデータを読み書きしますが、Firebaseは違います。

主な特徴は?

  • リアルタイムであること。
  • プラットフォームに依存しない。
  • アクセスコントロールが簡単。
  • NoSQLソリューションであり、パフォーマンスのために最適化されている。
  • オフライン機能。
  • ユーザーフレンドリー

ビデオチュートリアル より詳細な説明は、以下のビデオチュートリアルをご覧ください。

セットアップ

(a) .基本的なアクティビティプロジェクトの作成
  1. まず、android studioで新しいプロジェクトを作成します。File --> New Project を選択します。
(b). Firebaseの作成と設定ファイルのダウンロード

Firebase Consoleにアクセスし、Firebaseアプリを作成、アプリIDを登録し、google-services.jsonファイルをダウンロードします。アプリのフォルダに追加します。

(c). Maven リポジトリの URL を指定する

プロジェクトレベル(プロジェクトフォルダ)の build.gradle に移動し、以下の作業を行います。

  1. Googleサービスのクラスパスを以下のように追加します。
  2. mavenリポジトリのURLを追加

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.google.gms:google-services:3.1.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com" // Google's Maven repository
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
(d). Firebaseの依存関係の追加

アプリレベル(appフォルダ)のbuild.gradleに追加し、以下のようにします。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'com.android.support:cardview-v7:23.3.0'

    compile 'com.google.firebase:firebase-core:11.8.0'
    compile 'com.google.firebase:firebase-database:11.8.0'
}
apply plugin: 'com.google.gms.google-services'

プラグインの適用を確認します。com.google.gms.google-services'` を適用してください。

(e). AndroidManifest.xml
  • マニフェストファイルにインターネットに関する権限を追加することを忘れないでください。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.tutorials.hp.firebaserecyclermdetail">

    <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="Detail View"
            android_theme="@style/AppTheme.NoActionBar">
        </activity>
    </application>

</manifest>

Javaクラス

(a). スペースクラフト.java
  • 私たちのデータ・オブジェクト・クラスです
  • 空のコンストラクタを持たなければならない。
  • 他のコンストラクタを作成したり、データを渡したり、使用することができます。

package com.tutorials.hp.firebaserecyclermdetail.m_Model;

/*
 * 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;
    }
}
(b). FirebaseHelper.java
  • 基本的には、CRUDクラスです。
  • ここでは、Firebaseデータベースへの読み込みと書き込みを行っています。
  • データの永続化には、setValue()を使用しています。
  • setValue()メソッドを呼ぶ前に、push()を呼んで、データを置き換えるのではなく、データベースに追加することを保証しています。
  • 宇宙船のオブジェクトを配列リストに格納する。

package com.tutorials.hp.firebaserecyclermdetail.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.firebaserecyclermdetail.m_Model.Spacecraft;

import java.util.ArrayList;

/*
 * 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 THEN RETURN ARRAYLIST
    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;
    }
}
(c). MyViewHolder.java
  • ビューホルダーのクラスです。
  • RecyclerViewに表示するビューを保持します。

package com.tutorials.hp.firebaserecyclermdetail.m_UI;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.tutorials.hp.firebaserecyclermdetail.R;

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

    TextView nameTxt,propTxt,descTxt;
    ItemClickListener itemClickListener;

    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);

        itemView.setOnClickListener(this);
    }

    public void setItemClickListener(ItemClickListener itemClickListener)
    {
        this.itemClickListener=itemClickListener;
    }

    @Override
    public void onClick(View view) {
        this.itemClickListener.onItemClick(this.getLayoutPosition());
    }
}
(d). MyAdapter.java
  • Layout Inflation を担当します。
  • また、ビューへのデータバインディングも行います。
  • また、android.Content.Intentを介して、新しいアクティビティを開き、データを渡します。

package com.tutorials.hp.firebaserecyclermdetail.m_UI;

import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.tutorials.hp.firebaserecyclermdetail.DetailActivity;
import com.tutorials.hp.firebaserecyclermdetail.R;
import com.tutorials.hp.firebaserecyclermdetail.m_Model.Spacecraft;

import java.util.ArrayList;

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) {
        final  Spacecraft s=spacecrafts.get(position);

        holder.nameTxt.setText(s.getName());
        holder.propTxt.setText(s.getPropellant());
        holder.descTxt.setText(s.getDescription());

        holder.setItemClickListener(new ItemClickListener() {
            @Override
            public void onItemClick(int pos) {
                //OPEN DETAI ACTIVITY
                openDetailActivity(s.getName(),s.getDescription(),s.getPropellant());
            }
        });
    }

    @Override
    public int getItemCount() {
        return spacecrafts.size();
    }

    //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);
    }
}
(e). アイテムクリックリスナー(ItemClickListener).java
  • onItemClick()メソッドのシグネチャを定義しています。

package com.tutorials.hp.firebaserecyclermdetail.m_UI;

public interface ItemClickListener {

    void onItemClick(int pos);
}

12. MainActivity.java

  • ランチャーアクティビティです。
  • RecyclerViewを参照し、アダプタを設定します。
  • FABボタンクリック時に入力ダイアログを表示する。
  • DatabaseReferenceを初期化し、Firebaseの設定を行う。

package com.tutorials.hp.firebaserecyclermdetail;

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.firebaserecyclermdetail.m_FireBase.FirebaseHelper;
import com.tutorials.hp.firebaserecyclermdetail.m_Model.Spacecraft;
import com.tutorials.hp.firebaserecyclermdetail.m_UI.MyAdapter;

/*
1.INITIALIZE FIREBASE DB
2.INITIALIZE UI
3.DATA INPUT
 */
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);

        //SETUP RECYCLER
        rv = (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));

        //INITIALIZE FIREBASE DB
        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()
    {
        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 MyAdapter(MainActivity.this,helper.retrieve());
                        rv.setAdapter(adapter);

                    }
                }else
                {
                    Toast.makeText(MainActivity.this, "Name Must Not Be Empty", Toast.LENGTH_SHORT).show();
                }

            }
        });

        d.show();
    }

}
(f). DetailActivity.java
  • 詳細を表示するためのアクティビティです。
  • MainActivityからIntentでデータを受け取ります。
  • そのデータをTextViewsに表示します。

package com.tutorials.hp.firebaserecyclermdetail;

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();
            }
        });
    }

}

レイアウト

(a). ActivityMain.xml
  • ContentMain.xmlが含まれる。
  • Floating ActionButtonを定義しています。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_fitsSystemWindows="true"
    tools_context="com.tutorials.hp.firebaserecyclermdetail.MainActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_gravity="bottom|end"
        android_layout_margin="@dimen/fab_margin"
        android_src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
(b). ContentMain.xml
  • マスタービュー

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_paddingBottom="@dimen/activity_vertical_margin"
    android_paddingLeft="@dimen/activity_horizontal_margin"
    android_paddingRight="@dimen/activity_horizontal_margin"
    android_paddingTop="@dimen/activity_vertical_margin"
    app_layout_behavior="@string/appbar_scrolling_view_behavior"
    tools_context="com.tutorials.hp.firebaserecyclermdetail.MainActivity"
    tools_showIn="@layout/activity_main">

    <android.support.v7.widget.RecyclerView
        android_id="@+id/rv"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        />
</RelativeLayout>
(c). inputdialog.xml
  • 入力ダイアログのレイアウトを定義します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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>
(d). モデル.xml
  • カスタムCardViewsを定義しています。

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    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>
(f). activity_detail.xml
  • ContentDetail.xmlが格納されています。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_fitsSystemWindows="true"
    tools_context="com.tutorials.hp.firebaserecyclermdetail.DetailActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_detail" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_gravity="bottom|end"
        android_layout_margin="@dimen/fab_margin"
        android_src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
(g). content_detail.xml
  • 詳細ビューです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_paddingBottom="@dimen/activity_vertical_margin"
    android_paddingLeft="@dimen/activity_horizontal_margin"
    android_paddingRight="@dimen/activity_horizontal_margin"
    android_paddingTop="@dimen/activity_vertical_margin"
    app_layout_behavior="@string/appbar_scrolling_view_behavior"
    tools_context="com.tutorials.hp.firebaserecyclermdetail.DetailActivity"
    tools_showIn="@layout/activity_detail">

    <android.support.v7.widget.CardView
        android_orientation="horizontal" android_layout_width="match_parent"

        android_layout_margin="5dp"
        card_view_cardCornerRadius="10dp"
        card_view_cardElevation="5dp"

        android_layout_height="match_parent">

        <LinearLayout
            android_orientation="vertical"
            android_layout_width="match_parent"
            android_layout_height="match_parent"
            android_weightSum="1">

            <LinearLayout
                android_orientation="horizontal"
                android_layout_width="match_parent"
                android_layout_height="wrap_content">

                <ImageView
                    android_id="@+id/articleDetailImg"
                    android_layout_width="320dp"
                    android_layout_height="wrap_content"
                    android_paddingLeft="10dp"
                    android_layout_alignParentTop="true"
                    android_scaleType="centerCrop"
                    android_src="@drawable/spitzer" />

                <LinearLayout
                    android_orientation="vertical"
                    android_layout_width="match_parent"
                    android_layout_height="wrap_content">

                    <TextView
                        android_id="@+id/nameDetailTxt"
                        android_layout_width="wrap_content"
                        android_layout_height="wrap_content"
                        android_textAppearance="?android:attr/textAppearanceLarge"
                        android_padding="5dp"
                        android_minLines="1"
                        android_textStyle="bold"
                        android_textColor="@color/colorAccent"
                        android_text="Title" />

                </LinearLayout>
            </LinearLayout>

            <LinearLayout
                android_layout_width="fill_parent"
                android_layout_height="match_parent"
                android_layout_marginTop="?attr/actionBarSize"
                android_orientation="vertical"
                android_paddingLeft="5dp"
                android_paddingRight="5dp"
                android_paddingTop="5dp">

                <TextView
                    android_id="@+id/propellantDetailTxt"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_textAppearance="?android:attr/textAppearanceLarge"
                    android_padding="5dp"
                    android_minLines="1"
                    android_text="DATE" />
                <TextView
                    android_id="@+id/descDetailTxt"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_textAppearance="?android:attr/textAppearanceLarge"
                    android_padding="5dp"
                    android_textColor="#0f0f0f"
                    android_minLines="4"
                    android_text="Space craft details...." />

                <TextView
                    android_id="@+id/linkDetailTxt"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_textAppearance="?android:attr/textAppearanceMedium"
                    android_padding="5dp"
                    android_textColor="@color/colorPrimaryDark"
                    android_textStyle="italic"
                    android_text="Link" />

            </LinearLayout>
        </LinearLayout>
    </android.support.v7.widget.CardView>

</RelativeLayout>

4. ダウンロード

閲覧
ダウンロード

走る方法

  1. プロジェクトをダウンロードする。
  2. Zip圧縮されたファイルが届くので、それを解凍する。
  3. Android Studioを起動します。
  4. 既に開いているプロジェクトを閉じます。
  5. メニューバーから、File >New > Import Projectをクリックします。
  6. プロジェクトのインポート先のフォルダを選択します。
  7. Androidプロジェクトを選択します。
  8. "OK "をクリックします。
  9. プロジェクトのインポートが完了したら、編集を行います。
  10. Firebase Consoleにアクセスし、アプリを作成し、設定ファイルをダウンロードし、appフォルダ内のプロジェクトに追加する必要があります。

Categorized in: