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
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.
