How to change data in a recyclerview?

105 Views Asked by At

I have:

  • a roomdatabase connected to a table with columns: Family, Name and Number
  • a recycler view with cards that show Name and Number and an add-button
  • buttons marked "dogs" and "cats" beneath the recycler view

Snapshot

I want to:

  • be able to click on each animal to increase the number
  • use the buttons to only show animals from a certain family (cats or dogs)

I have tried different strategies, but I usually end up with a race between different observers.

Snippet from Main Acitivty:

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

        view_recycler = findViewById(R.id.recycler);
        view_recycler.setHasFixedSize(true);
        view_recycler.setLayoutManager(new LinearLayoutManager(this));

       family = "Cat";
        animalViewModel = new ViewModelProvider(MainActivity.this).get(AnimalViewModel.class);
        my_observer = animalList -> {
            animalViewAdapter = new AnimalViewAdapter(animalList,MainActivity.this);
            animalViewAdapter.updateAnimals(animalList);
            view_recycler.setAdapter(animalViewAdapter);
        };
        animalViewModel.getAnimals(family).observe(MainActivity.this, my_observer);

        Button cats = findViewById(R.id.cats);
        Button dogs = findViewById(R.id.dogs);

        cats.setOnClickListener(v -> {
            family = "Cat";
            updateViewModel();
        });

        dogs.setOnClickListener(v -> {
            family = "Dog";
            updateViewModel();
        });

    private void updateViewModel() {
        animalViewModel.getAnimals(family).removeObserver(my_observer);
        my_observer = null;
        my_observer = animalList -> {
            animalViewAdapter.updateAnimals(animalList);
            view_recycler.setAdapter(animalViewAdapter);
        };
        animalViewModel.getAnimals(family).observe(MainActivity.this, my_observer);
    }

    @Override
    public void onAnimalClick(int position) {
        Animal animal = Objects.requireNonNull(animalViewModel.animals.getValue()).get(position);
        animal.setNumber(animal.getNumber()+1);
        AnimalViewModel.update(animal);
    }

In this version I set my observer to null in a desperate attempt to get rid of the old when I update the ViewModel. I still get the race. Without the updateViewModel part, I can still increase the numbers, but not show another family.

My AnimalViewAdapter.java:

public class AnimalViewAdapter extends RecyclerView.Adapter<AnimalViewAdapter.ViewHolder> {
    private List<Animal> animals;
    private final OnAnimalClickListener onAnimalClickListener;

    public AnimalViewAdapter(List<Animal> animals, OnAnimalClickListener onAnimalClickListener) {
        this.animals = animals;
        this.onAnimalClickListener = onAnimalClickListener;
    }

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

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Animal animal = animals.get(position);
        holder.view_name.setText(animal.getName());
        holder.view_number.setText(String.valueOf(animal.getNumber()));
    }

    @Override
    public int getItemCount() {
        if (animals == null) { return 0; }
        return animals.size();
    }

    @SuppressLint("NotifyDataSetChanged")
    public void updateAnimals(List<Animal> animalList) {
        animals = animalList;
        notifyDataSetChanged();
    }

    static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView view_name, view_number;
        public ImageView view_add;
        OnAnimalClickListener onAnimalClickListener;

        public ViewHolder(@NonNull View itemView, OnAnimalClickListener onAnimalClickListener) {
            super(itemView);
            view_name = itemView.findViewById(R.id.name);
            view_number = itemView.findViewById(R.id.number);
            view_add = itemView.findViewById(R.id.add_number);
            this.onAnimalClickListener = onAnimalClickListener;

            view_add.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            onAnimalClickListener.onAnimalClick(getAdapterPosition());
        }
    }

    public interface OnAnimalClickListener {
        void onAnimalClick(int position);
    }

}

My AnimalViewModel.class simply gets LiveData from my repository which is connected to my RoomDatabase. Quite ordinary, I think.

0

There are 0 best solutions below