使用 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();

            });
        }));
    });