0

I've been breaking my head trying to figure out how to get the Firebase RecyclerAdapter to work, but cannot get through this point. I read a lot of threads on Stack Overflow, but can't figure it out.

I haven't completed the onBindViewHolder yet but, the onCreateViewHolder is not working either. the word "parent" is always in red.

The problem is in the AllUserActivitys.java file and I have provided the rest of the code as well.

Here is my code:

AllUsersActivity.java:

package com.example.android.whammychat;

import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class AllUsersActivity extends AppCompatActivity {

    private Toolbar mAllUsersToolBar;
    private RecyclerView mAllUsersRecyclerView;
    private DatabaseReference mAllUsersDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_all_users);

        mAllUsersToolBar = findViewById(R.id.allUsersToolBar);
        setSupportActionBar(mAllUsersToolBar);
        getSupportActionBar().setTitle("All Users");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        mAllUsersDatabase = FirebaseDatabase.getInstance().getReference().child("Users");

        mAllUsersRecyclerView = findViewById(R.id.allUsersRecyclerView);
        mAllUsersRecyclerView.setHasFixedSize(true);
        mAllUsersRecyclerView.setLayoutManager(new LinearLayoutManager(this));



    }

    //We are putting this in .onStart because we want to retrieve the data in real time.
    @Override
    protected void onStart() {
        super.onStart();


        FirebaseRecyclerOptions<Users> options =
                new FirebaseRecyclerOptions.Builder<Users>()
                        .setQuery(mAllUsersDatabase, Users.class)
                        .build();


        FirebaseRecyclerAdapter firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, UsersViewHolder>(options) {

            @NonNull
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
                View view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.individual_user, parent, false);

                return new UsersViewHolder(view);

            }

            @Override
            protected void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull Object model) {

            }

        };


    }


    public class UsersViewHolder extends RecyclerView.ViewHolder {

        View mView;

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

            /*
           itemView is a single row in the ListView.
           We are going to be using mView later to perform an onClickListener method on the ViewHolder.
             */
            mView = itemView;

        }
    }

}

Users.java:

package com.example.android.whammychat;

public class Users {

    public String username;
    public String status;
    public String image;

    //Constructor without parameters is also needed because: https://stackoverflow.com/questions/18993936/how-to-best-explain-and-use-empty-constructors-in-java
    public Users() {

    }

    public Users(String username, String status, String image) {
        this.username = username;
        this.status = status;
        this.image = image;
    }

    //Getters
    public String getUsername() {
        return username;
    }

    public String getStatus() {
        return status;
    }

    public String getImage() {
        return image;
    }


}

activity_all_users:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AllUsersActivity">

    <include
        android:id="@+id/allUsersToolBar"
        layout="@layout/app_bar"/>

    <view
        android:id="@+id/allUsersRecyclerView"
        class="android.support.v7.app.AlertController$RecycleListView"
        android:layout_width="match_parent"
        android:layout_height="512dp"
        android:layout_marginTop="56dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </view>

</android.support.constraint.ConstraintLayout>

individual_user.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="139dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/individualUserPictureImageView"
            android:layout_width="105dp"
            android:layout_height="100dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="20dp"
            android:src="@drawable/profile_pic"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/individualUserStatusTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginStart="24dp"
            android:layout_marginTop="12dp"
            android:text="TextView"
            android:textSize="18sp"
            app:layout_constraintStart_toEndOf="@+id/individualUserPictureImageView"
            app:layout_constraintTop_toBottomOf="@+id/individualUserNameTextView" />

        <TextView
            android:id="@+id/individualUserNameTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@+id/individualUserStatusTextView"
            android:layout_marginStart="24dp"
            android:layout_marginTop="28dp"
            android:text="TextView"
            android:textColor="@android:color/black"
            android:textSize="24sp"
            android:textStyle="bold"
            app:layout_constraintStart_toEndOf="@+id/individualUserPictureImageView"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>


</android.support.constraint.ConstraintLayout>

EDIT: The "RecyclerView.ViewHolder" in the AllUsersActivity.java file part is underlined in red now because it says that the FirebaseRecyclerAdapter is clashing with the android.support.v7.widget.RecyclerView.adapter. I tried deleting import android.support.v7.widget.RecyclerView; from the AllUsersActivity.java file but it keeps on automatically coming back. What can I do?

Fishie
  • 7
  • 1
  • 6

3 Answers3

0

The problem is in your onCreateViewHolder

Replace:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.individual_user, parent, false);

    return new UsersViewHolder(view);

}

With:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.individual_user, viewGroup, false);
    return new UsersViewHolder(view);

}
Atiq
  • 14,435
  • 6
  • 54
  • 69
  • Awesome this seems to be working. The "RecyclerView.ViewHolder" part is underlined in red now because it says that the FirebaseRecyclerAdapter is clashing with the android.support.v7.widget.RecyclerView.adapter. I tried deleting import android.support.v7.widget.RecyclerView; from the AllUsersActivity.java file but it keeps on automatically coming back. What can I do? – Fishie Sep 05 '18 at 10:03
0

To solve this, just change the following line of code:

View view = LayoutInflater.from(parent.getContext())
        .inflate(R.layout.individual_user, parent, false);

to

View view = LayoutInflater.from(viewGroup.getContext())
        .inflate(R.layout.individual_user, parent, false);

In your code, the partent view group is the viewGroup object that is coming as an argument in your onCreateViewHolder() method.

If you are interested, this is a recommended way in which you can retrieve data from a Firebase Realtime database and display it in a RecyclerView using FirebaseRecyclerAdapter.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
0

This code is working now. AllUsersActivity

public class AllUsersActivity extends AppCompatActivity {

    private Toolbar mAllUsersToolBar;
    private RecyclerView mAllUsersRecyclerView;
    FirebaseRecyclerAdapter<Users, UsersViewHolder> firebaseUsersAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_all_users);

        mAllUsersToolBar = findViewById(R.id.allUsersToolBar);
        setSupportActionBar(mAllUsersToolBar);
        getSupportActionBar().setTitle("All Users");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        mAllUsersRecyclerView = findViewById(R.id.allUsersRecyclerView);

        Query query = FirebaseDatabase.getInstance().getReference().child("Users"); // you can add child as .child("child_name");

        FirebaseRecyclerOptions<Users> options = new FirebaseRecyclerOptions.Builder<Users>()
                .setQuery(query, Users.class)
                .build();

         firebaseUsersAdapter = new FirebaseRecyclerAdapter<Users, UsersViewHolder>(
                options) {
            @Override
            protected void onBindViewHolder(UsersViewHolder holder, int position, Users model) {
                holder.mIndividualUserName.setText(model.getUsername());
                holder.mIndividualUserStatus.setText(model.getStatus());
                holder.mIndividualUserPicture.setImageDrawable(getDrawable(R.drawable.profile_pic));
            }

            @Override
            public UsersViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.individual_user, parent, false);
                return new UsersViewHolder(view);
            }
        };

        mAllUsersRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAllUsersRecyclerView.setAdapter(firebaseUsersAdapter);
        firebaseUsersAdapter.startListening();

    }

    @Override
    protected void onResume() {
        super.onResume();
        if(firebaseUsersAdapter != null){
            firebaseUsersAdapter.startListening();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(firebaseUsersAdapter != null){
            firebaseUsersAdapter.stopListening();
        }
    }
}

UsersViewHolder I extracted this class out of the activity, this gonna help you to have a better code.

public class UsersViewHolder extends RecyclerView.ViewHolder {

    protected ImageView mIndividualUserPicture;
    protected TextView mIndividualUserName;
    protected TextView mIndividualUserStatus;


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

        mIndividualUserPicture = itemView.findViewById(R.id.individualUserPictureImageView);
        mIndividualUserName = itemView.findViewById(R.id.individualUserNameTextView);
        mIndividualUserStatus = itemView.findViewById(R.id.individualUserStatusTextView);


    }
}

Also i made a little change in the individual_user layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="139dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/individualUserPictureImageView"
            android:layout_width="105dp"
            android:layout_height="100dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="20dp"
            android:src="@drawable/profile_pic"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/individualUserStatusTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginStart="24dp"
            android:layout_marginTop="12dp"
            android:text="TextView"
            android:textSize="18sp"
            app:layout_constraintStart_toEndOf="@+id/individualUserPictureImageView"
            app:layout_constraintTop_toBottomOf="@+id/individualUserNameTextView" />

        <TextView
            android:id="@+id/individualUserNameTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@+id/individualUserStatusTextView"
            android:layout_marginStart="24dp"
            android:layout_marginTop="28dp"
            android:text="TextView"
            android:textColor="@android:color/black"
            android:textSize="24sp"
            android:textStyle="bold"
            app:layout_constraintStart_toEndOf="@+id/individualUserPictureImageView"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>


</android.support.constraint.ConstraintLayout>

I tested this code and the app run as expected.

App: enter image description here

If you need something else, you can send me a message in my email address, you have it in your database ;)

Juanjo Berenguer
  • 789
  • 1
  • 5
  • 8
  • Thank you very much! Could you read the EDIT i added in the original post please? – Fishie Sep 05 '18 at 10:18
  • I edited my response, your firebaseRecyclerAdapter should use UsersViewHolder instead RecyclerView.ViewHolder. This should work. – Juanjo Berenguer Sep 05 '18 at 10:28
  • Okay that worked! The onBindViewHolder code you suggested is not working. After .setText(Users.) the get(position) method cannot be applied. What can I do here? – Fishie Sep 05 '18 at 10:37
  • There you need get the users that you are passing in the query. users is the parameter model in the onBindViewHolder, you can change the name model to users. – Juanjo Berenguer Sep 05 '18 at 10:42
  • Oh right slowly understanding this more. I've never understood though what the int position as a parameter does – Fishie Sep 05 '18 at 10:52
  • For some reason, the image view and the other two textviews don't appear in the recycler list even though I can go to the page. Is my FirebaseRecyclerOptions correct? Why isn't it appearing though in the RecyclerView? – Fishie Sep 05 '18 at 12:05
  • I edited the full code of onCreate() take a look. But I think you need search more info about RecyclerView implementation with Firebase. – Juanjo Berenguer Sep 05 '18 at 12:20
  • Dont worry Fishie. I have some time. I will check your code and i edit the answer fixing the code. – Juanjo Berenguer Sep 05 '18 at 13:23
  • Thank you very much! Looking forward to seeing the corrected code. I just don't know what I have done wrong. – Fishie Sep 05 '18 at 13:29
  • THANK YOU SO MUCH! Really happy that it's working! I made the Firebase Adapter in the onStart before because I thought it will update in real time. – Fishie Sep 05 '18 at 14:43
  • I am glad that you can keep working. You forgot use the adapter.startListener(). And i changed the layout because the rows was seted to the match parent instead the wrap content and the rows were very big. If you need something else just drop me a message in the email. Happy coding! – Juanjo Berenguer Sep 05 '18 at 14:44