使用 setOnClickListener 时如何重置 MutableLiveData 列表以显示新数据?
How to reset MutableLiveData list to display new data when using setOnClickListner?
所以我已经尝试了很长一段时间来使用 TMDB API 为我的应用程序添加搜索功能。
到目前为止,我设法做到的是第一次只能搜索电影,所以当我第二次尝试搜索电影时,问题就来了,它会继续向我显示旧电影列表第一个搜索结果,永远不会根据搜索更新列表。
例如,我搜索了一部蜘蛛侠电影,它会向我显示其中包含关键字蜘蛛侠的每一部电影,然后当我尝试再次搜索具有不同关键字的不同电影时,它会继续向我显示蜘蛛侠搜索的结果,所以有没有什么方法可以在每个 setOnClickListner
上重置 MutableLiveData
列表,这样我就可以在每次搜索时搜索和显示新电影?
提前致谢。
这里是 类:
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&page=1&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query);
}
public class SearchAPIManager {
Retrofit retrofit =
new Retrofit
.Builder()
.baseUrl("https://api.themoviedb.org/3/")
.addConverterFactory(GsonConverterFactory.create())
.build();
private final SearchMovieService searchMovieService = retrofit.create(SearchMovieService.class);
public void getMoviesWithSearching(MutableLiveData<List<Movie>> moviesLiveData, String query){
Call<MovieResponse> movieHTTPRequest = searchMovieService.getMoviesWithSearching(query);
movieHTTPRequest.enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
MovieResponse movieResponse = response.body();
if (movieResponse != null) {
ArrayList<Movie> movies = movieResponse.getMovies();
moviesLiveData.postValue(movies);
}
}
@Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
t.getMessage();
}
});
}
}
public class SearchMovieViewModel extends ViewModel {
private final MutableLiveData<List<Genre>> genresNames = new MutableLiveData<>();
private final MutableLiveData<List<Movie>> moviesSearching = new MutableLiveData<>();
public SearchMovieViewModel() {
GenreAPIManager genreManager = new GenreAPIManager();
genreManager.getGenreNames(genresNames);
SearchAPIManager searchManager = new SearchAPIManager();
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
public MutableLiveData<List<Genre>> getGenresNames() {
return genresNames;
}
public MutableLiveData<List<Movie>> getMoviesWithSearching() {
return moviesSearching;
}
}
public class SearchMovieFragment extends Fragment {
SearchMovieAdapter adapter;
private EditText etSearch;
private ImageButton ibSearch;
private RecyclerView rvMovieSearch;
private SearchMovieViewModel searchMovieViewModel;
public static SearchMovieFragment newInstance() {
return new SearchMovieFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.search_movie_fragment, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
etSearch = view.findViewById(R.id.etSearch);
ibSearch = view.findViewById(R.id.ibSearch);
rvMovieSearch = view.findViewById(R.id.rvMovieSearch);
rvMovieSearch.setLayoutManager(new VegaLayoutManager());
ibSearch.setOnClickListener(v -> {
if (etSearch.getText().toString().equals("")) {
etSearch.setError("Type Something");
return;
}
Constants.MOVIE_SEARCH = etSearch.getText().toString();
searchMovieViewModel = new ViewModelProvider(this).get(SearchMovieViewModel.class);
searchMovieViewModel.getMoviesWithSearching().observe(getViewLifecycleOwner(), (movies -> {
searchMovieViewModel.getGenresNames().observe(getViewLifecycleOwner(), genres -> {
adapter = new SearchMovieAdapter(movies, genres);
rvMovieSearch.setAdapter(adapter);
rvMovieSearch.scheduleLayoutAnimation();
});
}));
});
}
}
您需要更改查询中的页码,以便从 API
中获取更多数据
这里你 return 每个请求只 page=1
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&page=1&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query);
}
但是你可以将page
作为查询参数
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query,
(@Query("page") long page);
}
并在您请求 activity 中的服务时应用:
long page = 1;
Call<MovieResponse> movieHTTPRequest = searchMovieService.getMoviesWithSearching(query, page);
现在您可以随时增加 page
值以获取新的数据列表。
更新:
let's say i searched for a spiderman movie, it will show me every movie that has the keyword spiderman in it, and then when i try to search again for a different movie with a different keyword it will keep showing the results from spiderman search
MutableLiveData
实际上并没有被新查询触发,所以它的数据没有改变,你需要重新入队数据才能使MutableLiveData
更新底层正在观察的数据。
请注意,无论何时进行新查询,都不会再次调用 ViewModel 构造函数,因此您需要将 searchManager.getMoviesWithSearching()
添加到其他地方。
为此,您需要在 ViewModel 中添加一个方法来更新搜索
public class SearchMovieViewModel extends ViewModel {
private final MutableLiveData<List<Genre>> genresNames = new MutableLiveData<>();
private final MutableLiveData<List<Movie>> moviesSearching = new MutableLiveData<>();
public SearchMovieViewModel() {
GenreAPIManager genreManager = new GenreAPIManager();
genreManager.getGenreNames(genresNames);
SearchAPIManager searchManager = new SearchAPIManager();
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
public MutableLiveData<List<Genre>> getGenresNames() {
return genresNames;
}
public MutableLiveData<List<Movie>> getMoviesWithSearching() {
return moviesSearching;
}
public void updateMoviesWithSearching() {
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
}
然后在您想要更新列表时调用 updateMoviesWithSearching()
。还要确保使用查询
更新 Constants.MOVIE_SEARCH
每当您进行新查询时:调用 updateMoviesWithSearching()
ibSearch.setOnClickListener(v -> {
if (etSearch.getText().toString().equals("")) {
etSearch.setError("Type Something");
return;
}
Constants.MOVIE_SEARCH = etSearch.getText().toString();
searchMovieViewModel = new ViewModelProvider(this).get(SearchMovieViewModel.class);
searchMovieViewModel.updateMoviesWithSearching();
searchMovieViewModel.getMoviesWithSearching().observe(getViewLifecycleOwner(), (movies -> {
searchMovieViewModel.getGenresNames().observe(getViewLifecycleOwner(), genres -> {
adapter = new SearchMovieAdapter(movies, genres);
rvMovieSearch.setAdapter(adapter);
rvMovieSearch.scheduleLayoutAnimation();
});
}));
});
所以我已经尝试了很长一段时间来使用 TMDB API 为我的应用程序添加搜索功能。 到目前为止,我设法做到的是第一次只能搜索电影,所以当我第二次尝试搜索电影时,问题就来了,它会继续向我显示旧电影列表第一个搜索结果,永远不会根据搜索更新列表。
例如,我搜索了一部蜘蛛侠电影,它会向我显示其中包含关键字蜘蛛侠的每一部电影,然后当我尝试再次搜索具有不同关键字的不同电影时,它会继续向我显示蜘蛛侠搜索的结果,所以有没有什么方法可以在每个 setOnClickListner
上重置 MutableLiveData
列表,这样我就可以在每次搜索时搜索和显示新电影?
提前致谢。
这里是 类:
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&page=1&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query);
}
public class SearchAPIManager {
Retrofit retrofit =
new Retrofit
.Builder()
.baseUrl("https://api.themoviedb.org/3/")
.addConverterFactory(GsonConverterFactory.create())
.build();
private final SearchMovieService searchMovieService = retrofit.create(SearchMovieService.class);
public void getMoviesWithSearching(MutableLiveData<List<Movie>> moviesLiveData, String query){
Call<MovieResponse> movieHTTPRequest = searchMovieService.getMoviesWithSearching(query);
movieHTTPRequest.enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
MovieResponse movieResponse = response.body();
if (movieResponse != null) {
ArrayList<Movie> movies = movieResponse.getMovies();
moviesLiveData.postValue(movies);
}
}
@Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
t.getMessage();
}
});
}
}
public class SearchMovieViewModel extends ViewModel {
private final MutableLiveData<List<Genre>> genresNames = new MutableLiveData<>();
private final MutableLiveData<List<Movie>> moviesSearching = new MutableLiveData<>();
public SearchMovieViewModel() {
GenreAPIManager genreManager = new GenreAPIManager();
genreManager.getGenreNames(genresNames);
SearchAPIManager searchManager = new SearchAPIManager();
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
public MutableLiveData<List<Genre>> getGenresNames() {
return genresNames;
}
public MutableLiveData<List<Movie>> getMoviesWithSearching() {
return moviesSearching;
}
}
public class SearchMovieFragment extends Fragment {
SearchMovieAdapter adapter;
private EditText etSearch;
private ImageButton ibSearch;
private RecyclerView rvMovieSearch;
private SearchMovieViewModel searchMovieViewModel;
public static SearchMovieFragment newInstance() {
return new SearchMovieFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.search_movie_fragment, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
etSearch = view.findViewById(R.id.etSearch);
ibSearch = view.findViewById(R.id.ibSearch);
rvMovieSearch = view.findViewById(R.id.rvMovieSearch);
rvMovieSearch.setLayoutManager(new VegaLayoutManager());
ibSearch.setOnClickListener(v -> {
if (etSearch.getText().toString().equals("")) {
etSearch.setError("Type Something");
return;
}
Constants.MOVIE_SEARCH = etSearch.getText().toString();
searchMovieViewModel = new ViewModelProvider(this).get(SearchMovieViewModel.class);
searchMovieViewModel.getMoviesWithSearching().observe(getViewLifecycleOwner(), (movies -> {
searchMovieViewModel.getGenresNames().observe(getViewLifecycleOwner(), genres -> {
adapter = new SearchMovieAdapter(movies, genres);
rvMovieSearch.setAdapter(adapter);
rvMovieSearch.scheduleLayoutAnimation();
});
}));
});
}
}
您需要更改查询中的页码,以便从 API
中获取更多数据这里你 return 每个请求只 page=1
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&page=1&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query);
}
但是你可以将page
作为查询参数
public interface SearchMovieService {
@GET("search/movie?api_key=&language=en-US&include_adult=false")
Call<MovieResponse> getMoviesWithSearching(@Query("query") String query,
(@Query("page") long page);
}
并在您请求 activity 中的服务时应用:
long page = 1;
Call<MovieResponse> movieHTTPRequest = searchMovieService.getMoviesWithSearching(query, page);
现在您可以随时增加 page
值以获取新的数据列表。
更新:
let's say i searched for a spiderman movie, it will show me every movie that has the keyword spiderman in it, and then when i try to search again for a different movie with a different keyword it will keep showing the results from spiderman search
MutableLiveData
实际上并没有被新查询触发,所以它的数据没有改变,你需要重新入队数据才能使MutableLiveData
更新底层正在观察的数据。
请注意,无论何时进行新查询,都不会再次调用 ViewModel 构造函数,因此您需要将 searchManager.getMoviesWithSearching()
添加到其他地方。
为此,您需要在 ViewModel 中添加一个方法来更新搜索
public class SearchMovieViewModel extends ViewModel {
private final MutableLiveData<List<Genre>> genresNames = new MutableLiveData<>();
private final MutableLiveData<List<Movie>> moviesSearching = new MutableLiveData<>();
public SearchMovieViewModel() {
GenreAPIManager genreManager = new GenreAPIManager();
genreManager.getGenreNames(genresNames);
SearchAPIManager searchManager = new SearchAPIManager();
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
public MutableLiveData<List<Genre>> getGenresNames() {
return genresNames;
}
public MutableLiveData<List<Movie>> getMoviesWithSearching() {
return moviesSearching;
}
public void updateMoviesWithSearching() {
searchManager.getMoviesWithSearching(moviesSearching, Constants.MOVIE_SEARCH);
}
}
然后在您想要更新列表时调用 updateMoviesWithSearching()
。还要确保使用查询
Constants.MOVIE_SEARCH
每当您进行新查询时:调用 updateMoviesWithSearching()
ibSearch.setOnClickListener(v -> {
if (etSearch.getText().toString().equals("")) {
etSearch.setError("Type Something");
return;
}
Constants.MOVIE_SEARCH = etSearch.getText().toString();
searchMovieViewModel = new ViewModelProvider(this).get(SearchMovieViewModel.class);
searchMovieViewModel.updateMoviesWithSearching();
searchMovieViewModel.getMoviesWithSearching().observe(getViewLifecycleOwner(), (movies -> {
searchMovieViewModel.getGenresNames().observe(getViewLifecycleOwner(), genres -> {
adapter = new SearchMovieAdapter(movies, genres);
rvMovieSearch.setAdapter(adapter);
rvMovieSearch.scheduleLayoutAnimation();
});
}));
});