Search code examples
androidviewmodelsearchviewandroid-mvvm

Android - Searchview can only do one search only


I made a movie search feature with searchview. when I do the first search, then the data or list will appear, but when I want to search again with a new search word and then I submit, the next data or list does not appear and only displays the previous data. there is not even a reaction to finding the next data. when I go out and return to the fragment, the search will go on as before, is there a solution to this? thank you

MovieSearchFragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_search_movie, container, false);

    recyclerView = view.findViewById(R.id.recyclerView);
    searchView = view.findViewById(R.id.searchView);
    searchView.setOnQueryTextListener(this);

    setupRecyclerView();

    return view;
}    

private void loadMovie(String search) {

    search = searchView.getQuery().toString();

    SearchMovieViewModel viewModel = ViewModelProviders.of(Objects.requireNonNull(getActivity())).get(SearchMovieViewModel.class);
    viewModel.init(search);
    viewModel.getSeacrhMovie().observe(this, new Observer<MovieResponse>() {
        @Override
        public void onChanged(MovieResponse movieResponse) {
            if (movieResponse != null) {
                List<Movie> movies = movieResponse.getResults();
                searchMovieList.addAll(movies);
                adapter.notifyDataSetChanged();
                showLoading(false);
            } else {
                showLoading(false);
                showError();
            }
        }
    });
}

@Override
public boolean onQueryTextSubmit(String query) {
    showLoading(true);
    loadMovie(query);
    return false;
}

@Override
public boolean onQueryTextChange(String s) {
    return false;
}

private void setupRecyclerView() {
    if (adapter == null) {
        adapter = new MovieAdapter(getActivity(), searchMovieList);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAdapter(adapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setNestedScrollingEnabled(true);
    }
}

Viewmodel

public class SearchMovieViewModel extends ViewModel {
    private MutableLiveData<MovieResponse> mutableLiveData;

    public void init(String movieTitle) {
        if (mutableLiveData != null) {
            return;
        }

        Repository repository = Repository.getInstance();
        mutableLiveData = repository.getSearchMovie(BuildConfig.API_KEY, movieTitle);
    }

    public MutableLiveData<MovieResponse> getSeacrhMovie() {
       return mutableLiveData;
    }
}

Repository

public MutableLiveData<MovieResponse> getSearchMovie(String apiKey, String movieTitle) {
    final MutableLiveData<MovieResponse> searchData = new MutableLiveData<>();
    api.getSearchMovie(BuildConfig.API_KEY, movieTitle).enqueue(new Callback<MovieResponse>() {
        @Override
        public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
            if (response.isSuccessful()) {
                searchData.setValue(response.body());
            } else {
                searchData.setValue(null);
            }
        }

        @Override
        public void onFailure(Call<MovieResponse> call, Throwable t) {
            searchData.setValue(null);
        }
    });
    return searchData;
}

Solution

  • SOLVED

    I found the problem in my repository and then I replaced it with LiveData and added postValue as the recipient of the new value. Besides, I tried to put the adapter in my observer and changed a bit to the setupRecyclerView method. until finally the search feature can run properly, thanks for those who have helped

    MovieFragment

      @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_search_movie, container, false);
    
        progressBar = view.findViewById(R.id.progressBar);
        recyclerView = view.findViewById(R.id.recyclerView);
        searchView = view.findViewById(R.id.searchView);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                showLoading(true);
                loadMovie(query);
                return false;
            }
    
            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });
    
        setupRecyclerView();
    
        return view;
    }
    
    private void loadMovie(String title) {
        title = searchView.getQuery().toString();
    
        SearchMovieViewModel viewModel = ViewModelProviders.of(this).get(SearchMovieViewModel.class);
        viewModel.init(title);
        viewModel.getSearchMovie().observe(this, new Observer<MovieResponse>() {
            @Override
            public void onChanged(MovieResponse movieResponse) {
                if (movieResponse != null) {
                    List<Movie> movieList = movieResponse.getResults();
                    adapter = new MovieAdapter(getActivity(), movieList);
                    recyclerView.setAdapter(adapter);
                    adapter.notifyDataSetChanged();
                    showLoading(false);
                } else {
                    showLoading(false);
                    showError();
                }
            }
        });
    }
    
    private void setupRecyclerView() {
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setNestedScrollingEnabled(true);
    }
    

    ViewModel

    public class SearchMovieViewModel extends ViewModel {
    private LiveData<MovieResponse> movieLiveData;
    
    public void init(String movieTitle) {
        Repository repository = Repository.getInstance();
        movieLiveData = repository.getSearchMovie(BuildConfig.API_KEY, movieTitle);
    }
    
    public LiveData<MovieResponse> getSearchMovie() {
        return movieLiveData;
    }
    }
    

    Repository

      public LiveData<MovieResponse> getSearchMovie(String apiKey, String movieTitle) {
        final MutableLiveData<MovieResponse> searchData = new MutableLiveData<>();
        api.getSearchMovie(BuildConfig.API_KEY, movieTitle).enqueue(new Callback<MovieResponse>() {
            @Override
            public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
                if (response.isSuccessful()) {
                    searchData.postValue(response.body());
                    searchData.setValue(response.body());
                } else {
                    searchData.setValue(null);
                }
            }
    
            @Override
            public void onFailure(Call<MovieResponse> call, Throwable t) {
                searchData.setValue(null);
            }
        });
        return searchData;
    }