web-dev-qa-db-ja.com

空のビューを持つFirebaseRecyclerAdapter

RecyclerViewのビューを空にする方法はたくさんあることを私は知っています。しかし、私の質問はFirebaseRecyclerViewです。

私のレイアウトは次のとおりです。

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/feed_recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:scrollbars="vertical" />

<ProgressBar
    Android:id="@+id/feed_loading"
    style="?android:attr/progressBarStyle"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_centerInParent="true"
    Android:visibility="gone"/>
</RelativeLayout>

そのため、RecyclerViewがアイテムを埋める前に、LoadingProgressBarを表示しています。サーバーにアイテムがない場合はどうなりますか。この状況では、RecyclerViewは常に空であり、LoadingProgressBarは常にユーザーに表示されます。

そのため、ProgressBarを無期限に表示する代わりに、空のレイアウトを表示したいと思います。例えば。 「データが見つかりません」または同様のメッセージ。

最終結果は次のようになります。データがRecyclerViewにロードされるまで、ProgressBarが表示され、データがロードされると、ProgressBarは非表示になります。ただし、サーバーにデータが存在しない場合は、ProgressBarの代わりに空のレイアウトを表示する必要があります。

通常のRecyclerViewには、データセット(ArrayListなど)があり、それが空の場合は、その空のレイアウトを表示できます。しかし、FirebaseRecyclerAdapterの場合、アクティビティまたはコンテキストにスナップショットの参照がありません。また、サーバーにデータが存在しないことを通知するコールバックもありません。

回避策は大いに役立ちます。

18
Chandra Sekhar

これが私が試みることです。まず、以下にリンクされている質問に対する受け入れられた回答を確認してください。 Firebaseクエリがどのように機能するかについての非常に優れた洞察を提供します。答えはFirebaseチームの誰かによるものなので、信頼できる情報だと思います。

Firebaseを使用して初期データの読み込みを増分の子から分離する方法は?

したがって、上記のリンクされた質問への回答と、FirebaseRecyclerAdapterFirebaseArrayを使用して入力されたChildEventListenerによって裏付けられているという事実に基づいて、単一値イベントを追加します。 FirebaseRecyclerAdapterの設定に使用されたのと同じデータベース参照のリスナー。このようなもの:

//create database reference that will be used for both the
//FirebaseRecyclerAdapter and the single value event listener
dbRef = FirebaseDatabase.getInstance().getReference();

//setup FirebaseRecyclerAdapter
mAdapter = new FirebaseRecyclerAdapter<Model, YourViewHolder>(
                Model.class, R.layout.your_layout, YourViewHolder.class, dbRef) {

                @Override
                public void populateViewHolder(YourViewHolder holder, Model model, int position){

                     //your code for populating each recycler view item

                };

mRecyclerView.setAdapter(mAdapter);

//add the listener for the single value event that will function
//like a completion listener for initial data load of the FirebaseRecyclerAdapter
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
             @Override
             public void onDataChange(DataSnapshot dataSnapshot) {
                 //onDataChange called so remove progress bar

                 //make a call to dataSnapshot.hasChildren() and based 
                 //on returned value show/hide empty view 

                 //use helper method to add an Observer to RecyclerView    
             }

             @Override
             public void onCancelled(DatabaseError databaseError) {

             }
      });

これで、RecyclerViewの初期設定が処理されます。単一値イベントリスナーでonDataChangeが呼び出された場合、ヘルパーメソッドを使用してオブザーバーをFirebaseRecyclerAdapterに追加し、データベースの場所への後続の追加/削除を処理します。

mObserver = new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                //perform check and show/hide empty view
            }

            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                //perform check and show/hide empty view
            }
           };
mAdapter.registerAdapterDataObserver(mObserver);
24
Kevin O'Neil

からの回答: https://stackoverflow.com/a/40204298/2170278

最近のFirebaseUIアダプターには、データセットのロードが完了したことを検出するためにオーバーライドできるonDataChanged()メソッドがあります。

githubのソースコード を参照してください。そこから:

このメソッドは、データベースからの更新が完全に処理されるたびにトリガーされます。したがって、このメソッドが最初に呼び出されたとき、初期データがロードされています。これには、使用可能なデータがまったくない場合も含まれます。次回メソッドが呼び出されるたびに、完全な更新(複数の子アイテムの更新で構成される可能性があります)が完了します。

通常、このメソッドをオーバーライドして、(初期ロード後の)ロードインジケーターを非表示にするか、UI要素のバッチ更新を完了します。

FirebaseUIサンプルアプリはonDataChanged()をオーバーライドして、「読み込み中」インジケーターを非表示にします。

public void onDataChanged() {
    // If there are no chat messages, show a view that invites the user to add a message.
    mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
}