The submit function dosen't display all the data

52 views Asked by At

I have an issue when I submit the data to the ListAdapter, it doesn't show all the data.

View Model concept

So in my viewmodel I get the data from the firebase to display it. Here is how I approach it, there is a function called getAllStudents() this makes a get() on the Collection reference in firestore, the data returned is ids so I make another functions to get the actual data of the ids. However I think the problem is that everytime when I get the data of any id that is returned from the first call I post the data to the liveData so the data isn't complete this makes the ListAdatper submit this data but however it works at the end but there is items that is displayed with all of the data and other is not. Resulting this behavior : https://fastupload.io/xOb6Ara7S81WpIW/preview

The viewModel fuction example For example I have 4 functions every fun when it retrieves the data it calls the postValue() on the LiveData

Example

@Override
public void onSuccess(QuerySnapshot querySnapshot) {
    _uiState.postValue(false);

    for (DocumentSnapshot item:querySnapshot){

        Student studentItem = item.toObject(Student.class);

        if (studentItem.id.equals(student.id)){
            for (StudentDetails studentDetails:studentsDetailsList){
                if (studentDetails.studentId.equals(student.id)){
                    studentDetails.student = studentItem;
                    _studentsDetails.postValue(studentsDetailsList);
                }
            }
        }
    }
}

then each time any function calls success the ListAdatper calls submitList with the uncompleted data or completed (when the data is completed the adapter doesn't update all the items)

this is the observer which is attached to the liveData

viewModel.studentsDetails.observe(getViewLifecycleOwner(), new Observer<List<StudentDetails>>() {
    @Override
    public void onChanged(List<StudentDetails> students) {
        // Submitting the list to the recycler view adapter
        studentsAdapter.submitList(students);

        Log.e("observed", students.toString());

        if (students.isEmpty()){
            binding.containerNoData.setVisibility(VISIBLE);
        }else{
            binding.containerNoData.setVisibility(View.INVISIBLE);
        }
    }
});

and the diffutil of the list Adapter

new DiffUtil.ItemCallback<StudentDetails>() {
    @Override
    public boolean areItemsTheSame(@NonNull StudentDetails oldItem, @NonNull StudentDetails newItem) {
        return oldItem.id.equals(newItem.id);
    }

    @Override
    public boolean areContentsTheSame(@NonNull StudentDetails oldItem, @NonNull StudentDetails newItem) {
        return newItem.equals(oldItem) && newItem.toString().equals(oldItem.toString());
    }
});

NOTE: When I log the data observed it is correct

ViewModel class

@HiltViewModel
public class StudentsViewModel extends ViewModel {

    private StudentsRepository repository;

    private final MutableLiveData<Boolean> _uiState = new MutableLiveData<>(true);
    private final MutableLiveData<String> _error = new MutableLiveData<>("");
    public LiveData<Boolean> uiState = _uiState;
    public LiveData<String> error = _error;

    private final MutableLiveData<List<StudentDetails>> _studentsDetails = new MutableLiveData<>();
    public LiveData<List<StudentDetails>> studentsDetails = _studentsDetails;

    private List<StudentDetails> studentsDetailsList = new ArrayList<>();
    private  List<Student> students = new ArrayList<>();
    
    @Inject
    StudentsViewModel(StudentsRepository repository){
        this.repository = repository;
    }

    public void getAllStudents() {
        students = new ArrayList<>();
        studentsDetailsList = new ArrayList<>();
        _studentsDetails.postValue(studentsDetailsList);

        repository.getData(repository.getAllStudents(), null, new OnDataStateListener() {
            @Override
            public void onStart() {
                _uiState.postValue(true);
            }

            @Override
            public void onFailure(String exception) {
                _uiState.postValue(false);
                _error.postValue(exception);
            }

            @Override
            public void onSuccess(QuerySnapshot teachers) {
                List<Student> studentList = new ArrayList<>();
                for (DocumentSnapshot item:teachers.getDocuments()){
                    Student student = item.toObject(Student.class);
                    studentList.add(student);

                    StudentDetails newStudent = new StudentDetails();
                    newStudent.studentId = student.id;
                    studentsDetailsList.add(newStudent);
                }
                students.addAll(studentList);

                getStudent();
                getStudentDepartment();
                getStudentBatch();
                getStudentUser();
            }
        });

    }

    private void getStudent(){
        for (Student student : students){
            repository.getData(null, repository.getStudent(student.id), new OnDataStateListener() {
                @Override
                public void onStart() {
                    _uiState.postValue(true);
                }

                @Override
                public void onFailure(String exception) {
                    _uiState.postValue(false);
                    _error.postValue(exception);
                }

                @Override
                public void onSuccess(QuerySnapshot querySnapshot) {
                    _uiState.postValue(false);

                    for (DocumentSnapshot item:querySnapshot){

                        Student studentItem = item.toObject(Student.class);

                        if (studentItem.id.equals(student.id)){
                            for (StudentDetails studentDetails:studentsDetailsList){
                                if (studentDetails.studentId.equals(student.id)){
                                    studentDetails.student = studentItem;

                                    _studentsDetails.setValue(studentsDetailsList);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    private void getStudentDepartment(){
        for (Student student : students){
            repository.getData(null, repository.getStudentDepartment(student.department), new OnDataStateListener() {
                @Override
                public void onStart() {
                    _uiState.postValue(true);
                }

                @Override
                public void onFailure(String exception) {
                    _uiState.postValue(false);
                    _error.postValue(exception);
                }

                @Override
                public void onSuccess(QuerySnapshot querySnapshot) {
                    _uiState.postValue(false);

                    for (DocumentSnapshot item:querySnapshot){

                        Department department = item.toObject(Department.class);

                        if (department.id.equals(student.department)){
                            for (StudentDetails studentDetails:studentsDetailsList){
                                if (studentDetails.studentId.equals(student.id)){
                                    studentDetails.department = department;
                                    _studentsDetails.setValue(studentsDetailsList);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    private void getStudentBatch(){
        for (Student student : students){
            repository.getData(null, repository.getStudentBatch(student.batch), new OnDataStateListener() {
                @Override
                public void onStart() {
                    _uiState.postValue(true);
                }

                @Override
                public void onFailure(String exception) {
                    _uiState.postValue(false);
                    _error.postValue(exception);
                }

                @Override
                public void onSuccess(QuerySnapshot querySnapshot) {
                    _uiState.postValue(false);

                    for (DocumentSnapshot item:querySnapshot){

                        Batch batch = item.toObject(Batch.class);

                        if (batch.id.equals(student.batch)){
                            for (StudentDetails studentDetails:studentsDetailsList){
                                if (studentDetails.studentId.equals(student.id)){
                                    studentDetails.batch = batch;
                                    _studentsDetails.setValue(studentsDetailsList);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    private void getStudentUser(){
        for (Student student : students){
            repository.getData(null, repository.getUserById(student.user), new OnDataStateListener() {
                @Override
                public void onStart() {
                    _uiState.postValue(true);
                }

                @Override
                public void onFailure(String exception) {
                    _uiState.postValue(false);
                    _error.postValue(exception);
                }

                @Override
                public void onSuccess(QuerySnapshot querySnapshot) {
                    _uiState.postValue(false);

                    for (DocumentSnapshot item:querySnapshot){

                        User user = item.toObject(User.class);

                        if (user.id.equals(student.user)){
                            for (StudentDetails studentDetails:studentsDetailsList){
                                if (studentDetails.studentId.equals(student.id)){
                                    studentDetails.user = user;
                                    _studentsDetails.setValue(studentsDetailsList);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    public void refreshTeachers() {
        getAllStudents();
    }

    public void searchTeachers(String query){
                List<StudentDetails> filteredList = new ArrayList<>(studentsDetailsList.stream().filter(item -> item.student.name.toLowerCase().trim().contains(query.toLowerCase().trim())).collect(Collectors.toList()));
                _studentsDetails.postValue(filteredList);
    }
}
1

There are 1 answers

0
Pawan Harariya On

The is due to underlying implementation of the submitList() method. If you supply the same list, it doesn't do any checks, even if the items in the list are changed.

The DiffUtils's submitList() compares the submitted list to the previous list, and if you supply the same list again, it treats them as same, without considering any changes in the list items itself.

This is a weird behaviour, I too have wasted long hours debugging this in past. The solution is to pass a new list to the submitList() every time.

studentsAdapter.submitList(new ArrayList<Student>(students));