I'm new to android java programming. I'm using MVVM and I have a search method in my DAO. when I use that method to search for something in recyclerview, it works fine and I can update, delete and onClick on the result of search. However, after that, if I try to edit or delete an item directly, after I press the update or delete button, it shows the word that I searched for.
Below is my search method in DAO
@Query("SELECT * FROM vocabularytable WHERE Vocabulary LIKE '%' ||:vocabulary || '%' OR Definition LIKE '%' ||:vocabulary || '%'")
LiveData<List<Vocabulary>> search(String vocabulary);
Here is my RecyclerViewAdapter
public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.VIewHolder> {
private final List<Vocabulary> vocabularyList; // Original list
private final List<Vocabulary> displayList; // List used for displaying
private final Context context;
private final onVocabularyClickListener onVocabularyClickListener;
public RecycleViewAdapter(List<Vocabulary> vocabularyList, Context context, onVocabularyClickListener onVocabularyClickListener) {
this.vocabularyList = vocabularyList;
this.displayList = new ArrayList<>(vocabularyList);
this.context = context;
this.onVocabularyClickListener = onVocabularyClickListener;
}
@NonNull
@Override
public RecycleViewAdapter.VIewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_vocabulary, parent, false);
return new VIewHolder(view, onVocabularyClickListener);
}
@Override
public void onBindViewHolder(@NonNull RecycleViewAdapter.VIewHolder holder, int position) {
holder.vocabularyBind(displayList.get(position));
}
@Override
public int getItemCount() {
return displayList.size();
}
public class VIewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final AppCompatTextView tvVocabulary;
private final AppCompatTextView tvDefinition;
private final AppCompatImageButton imgBtnEdit;
private final AppCompatImageButton imgBtnDelete;
onVocabularyClickListener onVocabularyClickListener;
public VIewHolder(@NonNull View itemView, onVocabularyClickListener onVocabularyClickListener) {
super(itemView);
tvVocabulary = itemView.findViewById(R.id.tvVocabulary);
tvDefinition = itemView.findViewById(R.id.tvDefinition);
imgBtnEdit = itemView.findViewById(R.id.imgBtnEdit);
imgBtnDelete = itemView.findViewById(R.id.imgBtnDelete);
this.onVocabularyClickListener = onVocabularyClickListener;
itemView.setOnClickListener(this);
imgBtnEdit.setOnClickListener(this);
imgBtnDelete.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.imgBtnEdit) {
onVocabularyClickListener.onEditVocabularyClick(getAdapterPosition());
} else if (v.getId() == R.id.imgBtnDelete) {
onVocabularyClickListener.onDeleteVocabularyClick(getAdapterPosition());
} else {
onVocabularyClickListener.onVocabularyClick(getAdapterPosition());
}
}
public void vocabularyBind(Vocabulary vocabulary) {
tvVocabulary.setText(vocabulary.getVocabulary());
tvDefinition.setText(vocabulary.getDefinition());
}
}
public void filterList(List<Vocabulary> filteredList) {
displayList.clear();
displayList.addAll(filteredList);
notifyDataSetChanged();
}
public void resetList(List<Vocabulary> originalList) {
displayList.clear();
displayList.addAll(originalList);
notifyDataSetChanged();
}
public Vocabulary getVocabularyAtPosition(int position) {
return displayList.get(position);
}
public interface onVocabularyClickListener {
void onVocabularyClick(int position);
void onDeleteVocabularyClick(int position);
void onEditVocabularyClick(int position);
}
}
And here the MainActivity( I am using edit text for search
This is where I load dada to recyclerview for when I open the application( calling this method in onCreate
private void recyclerLoad() {
vocabularyViewModel = new ViewModelProvider.AndroidViewModelFactory(MainActivity.this.getApplication()).create(VocabularyViewModel.class);
vocabularyViewModel.getAllData.observe(this, vocabularies -> {
recycleViewAdapter = new RecycleViewAdapter(vocabularies, MainActivity.this, MainActivity.this);
recyclerView.setAdapter(recycleViewAdapter);
});
}
searchView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String query =s.toString();
if (!query.isEmpty()) {
vocabularyViewModel.search(query).observe(MainActivity.this, (List<Vocabulary> list) -> {
recycleViewAdapter.filterList(list);
});
} else {
searchView.clearFocus();
hideKeyboard(searchView);
refreshVocabularyList();
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
**Method for when I click on an item**
@Override
public void onVocabularyClick(int position) {
searchView.clearFocus();
DialogFragment.isDelete = false;
DialogFragment.isEdit = false;
Vocabulary vocabulary = recycleViewAdapter.getVocabularyAtPosition(position);
Bundle bundle = new Bundle();
bundle.putParcelable("vocabulary", vocabulary);
showFragment.setArguments(bundle);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainLayout, showFragment)
.addToBackStack(null)
.commit();
}
**For when I click on delete (imageButton) next to an item**
@Override
public void onDeleteVocabularyClick(int position) {
searchView.clearFocus();
DialogFragment.isEdit = false;
DialogFragment.isDelete = true;
Vocabulary vocabulary = recycleViewAdapter.getVocabularyAtPosition(position);
Bundle bundle = new Bundle();
bundle.putParcelable("vocabulary", vocabulary);
dialogFragment.setArguments(bundle);
dialogFragment.show(getSupportFragmentManager(), null);
}
**When I click on edit (imageButton) next to an item**
@Override
public void onEditVocabularyClick(int position) {
searchView.clearFocus();
DialogFragment.isDelete = false;
DialogFragment.isEdit = true;
Vocabulary vocabulary = recycleViewAdapter.getVocabularyAtPosition(position);
Bundle bundle = new Bundle();
bundle.putParcelable("vocabulary", vocabulary);
dialogFragment.setArguments(bundle);
dialogFragment.show(getSupportFragmentManager(), null);
}
**When I click on save button in a dialog to enter new words**
@Override
public void onDialogSave(Vocabulary vocabulary) {
if (vocabulary != null) {
searchView.clearFocus();
VocabularyViewModel.insert(vocabulary);
refreshVocabularyList(); // Refresh the list after saving
dialogFragment.dismiss();
}
}
**When I click on update button in the update dialog**
@Override
public void onDialogUpdate(Vocabulary vocabulary) {
if (vocabulary != null) {
VocabularyViewModel.update(vocabulary);
refreshVocabularyList(); //Refresh the list after updating
dialogFragment.dismiss();
} else {
Toast.makeText(this, "Please fill all the fields", Toast.LENGTH_SHORT).show();
}
}
**When I click on delete button in the delete dialog**
@Override
public void onDialogDelete(Vocabulary vocabulary) {
if (vocabulary != null) {
VocabularyViewModel.delete(vocabulary);
refreshVocabularyList(); //Refresh the list after deleting
dialogFragment.dismiss();
}
}
private void refreshVocabularyList() {
vocabularyViewModel.getAllData.observe(MainActivity.this, vocabularies ->{
/*vocabularyList.clear();
vocabularyList.addAll(vocabularies);*/
recycleViewAdapter.resetList(vocabularies); // Reset to original list
});
}
First I search for a word. it shows and I can click on it, edit or delete it from now on, if I try to edit or delete a word directly from the list( not searching for that),after I do that, it shows the word that is in the search list not the whole list or the whole updated list, or now it shows nothing. it used to show the word I searched for
I think what you have is a case of not setting your text field to ""
after your model VocabularyViewModel
For example
Add this bit of code below to all your functions such as onDialogUpdate
, onDialogSave
and onDialogDelete
searchView.setText(""); // clears your search field
Looking at the android docs closely android
I think we need to remove the observerable before starting a new search this should work
searchView.addTextChangedListener(new TextWatcher() {
private LiveData<List<Vocabulary>> searchLiveData;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String query = s.toString();
if (!query.isEmpty()) {
if (searchLiveData != null) {
// Remove the old observer before starting a new search
searchLiveData.removeObservers(MainActivity.this);
}
searchLiveData = vocabularyViewModel.search(query);
searchLiveData.observe(MainActivity.this, list -> {
recycleViewAdapter.filterList(list);
});
} else {
searchView.clearFocus();
hideKeyboard(searchView);
refreshVocabularyList();
}
}
@Override
public void afterTextChanged(Editable s) {}
});