1

Currently I can display all of the items in my RecyclerView. What I wish to do is calculate how many of these items there are. My items are saved in CardView. I don't want to calculate or sum any particular field, just the number of actual items. Here is my code and I have tried to set it up using getItemCount() method and attach this to a TextView and display outside of RecyclerView. This is not working for me:

public class COM800s1 extends AppCompatActivity {

private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference attendanceRef = db.collection("Attendance");
private AttendanceAdapter adapter;
private Context context;
private TextView attendanceNumbers;
private int counter;


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

    attendanceNumbers = findViewById(R.id.attendanceNums);

    FloatingActionButton floatingActionButton = findViewById(R.id.button_add_session);
    floatingActionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(new Intent(COM800s1.this,NewAttendanceRecord.class));
        }
    });

    setUpRecyclerView();


}

private void setUpRecyclerView() {
    final Query query = attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").orderBy("userEmail", Query.Direction.ASCENDING);

    FirestoreRecyclerOptions<Attendance> options = new FirestoreRecyclerOptions.Builder<Attendance>()
            .setQuery(query, Attendance.class).build();


    adapter = new AttendanceAdapter(options);



    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);

   //counter = adapter.getItemCount();
   //attendanceNumbers.setText("Currently " +counter+ " students have attended this session");


    new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            adapter.deleteItem(viewHolder.getAdapterPosition());
        }
    }).attachToRecyclerView(recyclerView);

    adapter.setSetOnItemClickListener(new AttendanceAdapter.OnItemClickListener() {

        @Override
        public void onItemClick(Attendance documentSnapshot, int position) {

        }
    });

}

    @Override
    protected void onStart () {
        super.onStart();
        adapter.startListening();
    }

    @Override
    protected void onStop(){
        super.onStop();
        adapter.stopListening();
    }

}

Here is my Adapter code:

public class AttendanceAdapter extends FirestoreRecyclerAdapter<Attendance, AttendanceAdapter.AttendanceHolder>{

private AttendanceAdapter.OnItemClickListener listener;

public AttendanceAdapter(@NonNull FirestoreRecyclerOptions<Attendance> options) {
    super(options);
}

@Override
protected void onBindViewHolder(@NonNull AttendanceHolder holder, int position, @NonNull Attendance model) {
    holder.textViewStudent.setText(model.getUserEmail());
    holder.textViewTime.setText(model.getSignInTime());
    holder.textViewSession.setText(model.getSessionID());
    holder.textViewUserUID.setText(model.getUserUID());
}

@NonNull
@Override
public AttendanceHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.attendance_item, parent, false);
    return new AttendanceAdapter.AttendanceHolder(v);
    }

public void deleteItem(int position){
    getSnapshots().getSnapshot(position).getReference().delete();
}

public int countItems(){
    return getItemCount();
}

class AttendanceHolder extends RecyclerView.ViewHolder {
    TextView textViewStudent;
    TextView textViewTime;
    TextView textViewSession;
    TextView textViewUserUID;

    public AttendanceHolder(View itemView){
        super(itemView);
        textViewStudent = itemView.findViewById(R.id.text_view_student_name);
        textViewTime = itemView.findViewById(R.id.text_view_course);
        textViewSession = itemView.findViewById(R.id.text_view_student_ID);
        textViewUserUID = itemView.findViewById(R.id.text_view_user_UID);


        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = getAdapterPosition();
                if (position != RecyclerView.NO_POSITION && listener != null){
                    listener.onItemClick(getSnapshots().get(position),position);
                }

            }
        });
    }
    }

public interface  OnItemClickListener{
    void onItemClick(Attendance documentSnapshot, int position);
}

public void setSetOnItemClickListener(AttendanceAdapter.OnItemClickListener listener){
    this.listener = listener;
}

Here is my updates code which returns null pointer object on the onClickListener:

public class COM800s1 extends AppCompatActivity {

private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference attendanceRef = db.collection("Attendance");
private AttendanceAdapter adapter;
private TextView attendanceNumbers;
private TextView attendanceNumbs;
private Button attendanceButton;




@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_com800s1);
    attendanceNumbs = findViewById(R.id.attendanceNums);
    attendanceButton = findViewById(R.id.calculateAttendance);



    FloatingActionButton floatingActionButton = findViewById(R.id.button_add_session);
    floatingActionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(new Intent(COM800s1.this,NewAttendanceRecord.class));
        }
    });

    setUpRecyclerView();

    attendanceButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {


                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        int count = 0;
                        for (DocumentSnapshot document : task.getResult()) {
                            count++;
                            attendanceNumbs = findViewById(R.id.attendanceNums);
                            attendanceNumbs.setText(count);
                        }
                        Log.d("TAG", count + "");
                    } else {

                    }
                }
            });

        }
    });


}

private void setUpRecyclerView() {
    final Query query = attendanceRef.whereEqualTo("sessionID", "5I0PLcpgmwdcjKLYLgkU").orderBy("userEmail", Query.Direction.ASCENDING);

    FirestoreRecyclerOptions<Attendance> options = new FirestoreRecyclerOptions.Builder<Attendance>()
            .setQuery(query, Attendance.class).build();



    adapter = new AttendanceAdapter(options);

    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);



    new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            adapter.deleteItem(viewHolder.getAdapterPosition());
        }
    }).attachToRecyclerView(recyclerView);

    adapter.setSetOnItemClickListener(new AttendanceAdapter.OnItemClickListener() {

        @Override
        public void onItemClick(Attendance documentSnapshot, int position) {

        }
    });

}

    @Override
    protected void onStart () {
        super.onStart();
        adapter.startListening();

    }

    @Override
    protected void onStop(){
        super.onStop();
        adapter.stopListening();
    }

}

3 Answers3

0

If you want to get the list of your recyclerView just create a static method in your recyclerView's adapter and just return your list in that.

for example:

public static List<modelOfYourList> getCount(){
   return yourAdapterList;
}
Ehsan
  • 2,676
  • 6
  • 29
  • 56
0

Perhaps add something like this to your AttendanceAdapter class?

I took a look at the FirestoreRecyclerOptionsclass, which exposes a getSnapshots() method. This returns a ObservableSnapshotArray, which in turn extends from Base ObservableSnapshotArray, which exposes a size() method.

class AttendanceAdapter extends FirestoreRecyclerAdapter<Attendance, AttendanceAdapter.AttendanceHolder>{
{ 
    private FirestoreRecyclerOptions<Attendance> options;

    public AttendanceAdapter(@NonNull FirestoreRecyclerOptions<Attendance> options)
    {
        super(options);
        this.options = options;
    }

    @Override
    public int getItemCount()
    {
        final int count = options.getSnapshots() != null 
            ? options.getSnapshots().size() 
            : 0;

        return count;
    }

Sources:

  1. FirestoreRecyclerOptions
  2. ObservableSnapshotArray
  3. BaseObservableSnapshotArray

Update: I see that the FirestoreRecyclerAdapter already has a getItemCount method already and you are calling it. Perhaps the data has not yet returned? What are you seeing for the count when you print it?

VIN
  • 6,385
  • 7
  • 38
  • 77
  • I have used your getItemCount method above although don't know how to call this now in my original activity? –  Aug 31 '18 at 18:02
  • When I add this code the app crashes. any suggestion why this would happen? –  Aug 31 '18 at 18:13
  • Would you be able to post the crash log/stack trace? – VIN Sep 01 '18 at 15:47
0

If you are trying to make the counter variable as a global variable and use it outside the callback it will always be null because as @Vinnie mentioned in his answer, the data has not finished loading yet. What's really happening is that you are trying to get the data from the database and immediately use it it while the counter variable has the initial value of 0. Then, when getting the data from the database completes, it changes counter's value, but it's never read again. To solve this, the use result of your getItemCount() method inside your adapter class to set it's value to the TextView.

If you want to count the number of documents beneath a collection, please also see my answer from this post.

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