Search code examples
android-recyclerview

Using search functionality in RecyclerView and receiving the same result for every action


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


Solution

  • 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) {}
    });