Android - Searchview 只能进行一次搜索
Android - Searchview can only do one search only
我用 searchview 做了一个电影搜索功能。当我第一次搜索时,数据或列表会出现,但是当我想用新的搜索词再次搜索然后提交时,下一个数据或列表不会出现,只显示以前的数据。甚至没有找到下一个数据的反应。当我出去 return 到片段时,搜索会像以前一样继续,有解决办法吗?谢谢
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);
}
}
视图模型
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;
}
}
存储库
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;
}
我认为问题出在您的存储库中,您在每次调用时都在其中实例化了新的 MutableLiveData。您应该观察一个 MutableLiveData,并且您应该在每次收到新响应时对该 MutableLiveData 调用 postValue,以便观察者(在 Activity/Fragment 中)获取新数据。
已解决
我在我的存储库中发现了问题,然后我将其替换为 LiveData 并添加了 postValue 作为新值的接收者。此外,我尝试将适配器放在我的观察者中,并对 setupRecyclerView 方法进行了一些更改。终于搜索功能可以运行正常了,感谢大家的帮助
电影片段
@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;
}
}
存储库
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;
}
我用 searchview 做了一个电影搜索功能。当我第一次搜索时,数据或列表会出现,但是当我想用新的搜索词再次搜索然后提交时,下一个数据或列表不会出现,只显示以前的数据。甚至没有找到下一个数据的反应。当我出去 return 到片段时,搜索会像以前一样继续,有解决办法吗?谢谢
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);
}
}
视图模型
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;
}
}
存储库
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;
}
我认为问题出在您的存储库中,您在每次调用时都在其中实例化了新的 MutableLiveData。您应该观察一个 MutableLiveData,并且您应该在每次收到新响应时对该 MutableLiveData 调用 postValue,以便观察者(在 Activity/Fragment 中)获取新数据。
已解决
我在我的存储库中发现了问题,然后我将其替换为 LiveData 并添加了 postValue 作为新值的接收者。此外,我尝试将适配器放在我的观察者中,并对 setupRecyclerView 方法进行了一些更改。终于搜索功能可以运行正常了,感谢大家的帮助
电影片段
@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;
}
}
存储库
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;
}