Search code examples
androidfirebasefirebase-realtime-databasefirebaseui

Why My FirebaseRecylerAdapter Not Working Properly?


I am trying to display all child "name" located in My Database tree. I used this answer given by @Alex Mamo Unable to get All child data in Firebase Database using a Map? I want to display all the data into a recyclerView. But for some reasons instead of getting all names(Eva, smith, princess) on my Screen Phone, I am only able to see one "princess" which is being displayed 3 times in my recyclerView layout(princess, princess, princess). After playing around with Alex's answer, I found this worked perfectly in my case,

 DatabaseReference yourRef = FirebaseDatabase.getInstance().getReference().child("Users");
        ValueEventListener eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                    String name = dataSnapshot1.child("name").getValue().toString();
                    displayName.setText(name);// display on the screen

                    Toast.makeText(context, name, Toast.LENGTH_LONG).show();

                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {}
        };
        yourRef.addListenerForSingleValueEvent(eventListener);
    }

So since this answer give me all names correctly in a Toast but not on my screen, so I assume that something is wrong with my FirebaseRecyclerAdpater. Here my code so far,

FirebaseRecyclerAdapter<UsersPostClass,  UsersViewHolder> userList = new FirebaseRecyclerAdapter<UsersPostClass,  UsersViewHolder>(
            UsersPostClass.class,
            R.layout.custom,
             UsersViewHolder.class,
            mDatabaseRef
    ) {
        @Override
        protected void populateViewHolder( UsersViewHolder viewHolder, UsersPostClass model, int position) {
            viewHolder.setUsernameList(getApplicationContext());


        }
    };
    mRecyclerView.setAdapter(userList);
}

private static class  UsersViewHolder extends RecyclerView.ViewHolder {
    View mView;

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

        mView = itemView;

    }

    public void setUsernameList(final Context context) {
        final TextView displayName = (TextView) mView.findViewById(R.id.listViewUsername);
        DatabaseReference yourRef = FirebaseDatabase.getInstance().getReference().child("Users");
        ValueEventListener eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                    String name = dataSnapshot1.child("name").getValue().toString();
                    displayName.setText(name);

                    Toast.makeText(context, name, Toast.LENGTH_LONG).show();

                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        };
        yourRef.addListenerForSingleValueEvent(eventListener);
    }
}

Any Help or tip is welcome. EDIT: Adding my Layout This is my RecyclerView Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:text="My Players List"
    android:textAppearance="@style/TextAppearance.AppCompat.Body2"
    android:textSize="20sp"
    android:layout_marginBottom="10dp"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Lastly my Custom Layout where I want to display all Names

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardBackgroundColor="@android:color/transparent"
    card_view:cardElevation="0dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp">


        <TextView
            android:id="@+id/listViewUsername"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:gravity="center_vertical"
            android:text="Username"
            android:textColor="#aaa"/>

    </RelativeLayout>

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

Just to have a Visual of what I am talking this a Screenshot of what I am getting(princess, princess, princess) when I should get (Eva,smith, princess). My ScreenShot If you look closer down you can see the Toast is returning "Eva" and 2 other names properly but not on Screen.


Solution

  • displayName.setText(name);// display on the screen
    

    You put this in a loop, where displayName is only a singluar UI element. In other words, you'll always only see the very last name from the loop.

    If you notice, your linked post there doesn't have any loop

    You need to populate some ArrayList

    List<String> names = new ArrayList<>();
    
    for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
        String name = dataSnapshot1.child("name").getValue().toString();
        names.add(name);
    }
    
    displayName.setText(names.toString());
    Toast.makeText(context, names.toString(), Toast.LENGTH_LONG).show();
    

    You can use that list in your RecyclerView, instead