I am training to work with api and the problem arose that when scrolling the RecyclerView, I need the data to be added, namely, "page" is added, and thus the content is added. I have achieved that before reaching the end of the list, the "onReachEndListener" method is triggered, but I cannot understand the implementation of adding to the sheet. PLEASE HELP ME!
public class MainActivity extends AppCompatActivity {
private SwitchMaterial switchMaterial;
private TextView textViewPopularity, textViewTopRated;
private RecyclerView recyclerViewPosters;
private MovieAdapter movieAdapter;
private MainViewModel viewModel;
private ProgressBar progressBar;
private static final int LOADER_ID = 122;
private LoaderManager loaderManager;
private static int page = 1;
private static String methodOfSort;
private static boolean isLoaning = true;
private static String lang;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.itemMain:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
break;
case R.id.itemFavourite:
Intent i = new Intent(this, FavouriteActivity.class);
startActivity(i);
break;
}
return super.onOptionsItemSelected(item);
}
private int getColumnCount() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = (int) (displayMetrics.widthPixels / displayMetrics.density);
return width / 185 > 2 ? width / 2 : 2;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lang = Locale.getDefault().getLanguage();
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
recyclerViewPosters = findViewById(R.id.recyclerViewPosters);
switchMaterial = findViewById(R.id.switchSort);
textViewPopularity = findViewById(R.id.textViewPopularity);
textViewTopRated = findViewById(R.id.textViewTopRated);
progressBar = findViewById(R.id.progressBarLoading);
movieAdapter = new MovieAdapter();
recyclerViewPosters.setLayoutManager(new GridLayoutManager(this, getColumnCount()));
recyclerViewPosters.setAdapter(movieAdapter);
switchMaterial.setChecked(true);
myOnClick();
LiveData<List<Movie>> moviesFromLiveData = viewModel.getMovies();
moviesFromLiveData.observe(this, new Observer<List<Movie>>() {
@Override
public void onChanged(@Nullable List<Movie> movies) {
movieAdapter.setMovies(movies);
}
});
}
private void myOnClick() {
switchMaterial.setOnCheckedChangeListener((compoundButton, b) -> {
page = 1;
setMethodOfSort(b);
});
switchMaterial.setChecked(false);
textViewPopularity.setOnClickListener(view -> {
setMethodOfSort(false);
switchMaterial.setChecked(false);
});
textViewTopRated.setOnClickListener(view -> {
setMethodOfSort(true);
switchMaterial.setChecked(true);
});
movieAdapter.setOnPosterClickListener(position -> {
Movie movie = movieAdapter.getMovies().get(position);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("id", movie.getId());
startActivity(intent);
});
movieAdapter.setOnReachEndListener(() -> {
if (!isLoaning){
viewModel.deleteAllMovies();
progressBar.setVisibility(View.VISIBLE);
viewModel.loadDataImage(lang, methodOfSort, Integer.toString(page));
Log.d("isLoaning", Integer.toString(page));
}
});
recyclerViewPosters.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1)) {
Log.d("isLoaning", Integer.toString(page));
LiveData<List<Movie>> moviesFromLiveData = viewModel.getMovies();
moviesFromLiveData.observe(MainActivity.this, new Observer<List<Movie>>() {
@Override
public void onChanged(@Nullable List<Movie> movies) {
viewModel.insertMovie(movies);
movieAdapter.addMovies(movies);
page++;
isLoaning = false;
}
});
}
}
});
}
private void setMethodOfSort(boolean b){
if(b) {
methodOfSort = SORT_BY_TOP_RATED;
Log.d("setMethodOfSort", methodOfSort);
textViewPopularity.setTextColor(getResources().getColor(R.color.white));
textViewTopRated.setTextColor(getResources().getColor(R.color.teal_200));
}
else {
methodOfSort = SORT_BY_POPULARITY;
Log.d("setMethodOfSort", methodOfSort);
textViewPopularity.setTextColor(getResources().getColor(R.color.teal_200));
textViewTopRated.setTextColor(getResources().getColor(R.color.white));
}
viewModel.loadData(lang, methodOfSort ,Integer.toString(page));
}
Model:
public class MainViewModel extends AndroidViewModel {
private static MovieDatabase database;
private LiveData<List<Movie>> movies;
private LiveData<List<FavouriteMovie>> favouriteMovies;
private LiveData<String> methodOfSort;
private CompositeDisposable compositeDisposable;
private MutableLiveData<Throwable> errors;
public static final String SMALL_POSTER_SIZE = "w185";
private static final String KEY_POSTER_PATH = "poster_path";
public static final String SORT_BY_POPULARITY = "popularity.desc";
public static final String SORT_BY_TOP_RATED = "vote_average.desc";
public static final int POPULARITY = 0;
public static final int TOP_RATED = 1;
public MainViewModel(@NonNull Application application) {
super(application);
database = MovieDatabase.getInstance(getApplication());
movies = database.movieDao().getAllMovies();
favouriteMovies = database.movieDao().getAllFavouriteMovies();
errors = new MutableLiveData<>();
}
public LiveData<Throwable> getErrors() {
return errors;
}
public void clearErrors() {
errors.setValue(null);
}
public void loadData(String lang, String sort, String page) {
ApiFactory apiFactory = ApiFactory.getInstance();
ApiService apiService = apiFactory.getApiService();
compositeDisposable = new CompositeDisposable();
Disposable disposable = apiService.getMovieResponse("32f91e104228c0c9ff3630899838e82e",
lang,
sort,
"1000",
page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<MovieResponse>() {
@Override
public void accept(MovieResponse movieResponse) throws Exception {
deleteAllMovies();
insertMovie(movieResponse.getMovies());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
errors.setValue(throwable);
}
});
compositeDisposable.add(disposable);
}
public void loadDataImage(String lang, String sort, String page) {
ApiFactory apiFactory = ApiFactory.getInstance();
ApiService apiService = apiFactory.getApiService();
compositeDisposable = new CompositeDisposable();
Disposable disposable = apiService.getMovieResponse(
"32f91e104228c0c9ff3630899838e82e",
lang,
sort,
"1000",
page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<MovieResponse>() {
@Override
public void accept(MovieResponse movieResponse) throws Exception {
insertMovie(movieResponse.getMovies());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
errors.setValue(throwable);
}
});
compositeDisposable.add(disposable);
}
public Movie getMovieById(int id) {
try {
return new GetMovieTask().execute(id).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public FavouriteMovie getFavouriteMovieById(int id) {
try {
return new GetFavouriteMovieTask().execute(id).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public LiveData<List<FavouriteMovie>> getFavouriteMovies() {
return favouriteMovies;
}
public void deleteAllMovies() {
new DeleteMoviesTask().execute();
}
@SuppressWarnings("unchecked")
public void insertMovie(List<Movie> movie) {
new InsertTask().execute(movie);
}
public void deleteMovie(Movie movie) {
new DeleteTask().execute(movie);
}
public LiveData<List<Movie>> getMovies() {
return movies;
}
public void insertFavouriteMovie(FavouriteMovie movie) {
new InsertFavouriteTask().execute(movie);
}
public void deleteFavouriteMovie(FavouriteMovie movie) {
new DeleteFavouriteTask().execute(movie);
}
private static class DeleteFavouriteTask extends AsyncTask<FavouriteMovie, Void, Void> {
@Override
protected Void doInBackground(FavouriteMovie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().deleteFavouriteMovie(movies[0]);
}
return null;
}
}
private static class InsertFavouriteTask extends AsyncTask<FavouriteMovie, Void, Void> {
@Override
protected Void doInBackground(FavouriteMovie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().insertFavouriteMovie(movies[0]);
}
return null;
}
}
private static class DeleteTask extends AsyncTask<Movie, Void, Void> {
@Override
protected Void doInBackground(Movie... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().deleteMovie(movies[0]);
}
return null;
}
}
private static class InsertTask extends AsyncTask<List<Movie>, Void, Void> {
@Override
protected Void doInBackground(List<Movie>... movies) {
if (movies != null && movies.length > 0) {
database.movieDao().insertMovie(movies[0]);
}
return null;
}
}
private static class DeleteMoviesTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... integers) {
database.movieDao().deleteAllMovies();
return null;
}
}
private static class GetMovieTask extends AsyncTask<Integer, Void, Movie> {
@Override
protected Movie doInBackground(Integer... integers) {
if (integers != null && integers.length > 0) {
return database.movieDao().getMovieById(integers[0]);
}
return null;
}
}
private static class GetFavouriteMovieTask extends AsyncTask<Integer, Void, FavouriteMovie> {
@Override
protected FavouriteMovie doInBackground(Integer... integers) {
if (integers != null && integers.length > 0) {
return database.movieDao().getFavouriteMovieById(integers[0]);
}
return null;
}
}
@Override
protected void onCleared() {
compositeDisposable.dispose();
super.onCleared();
}
}
Adapter:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movie> movies;
private OnPosterClickListener onPosterClickListener;
private OnReachEndListener onReachEndListener;
private onStartLoadingListener onStartLoadingListener;
public MovieAdapter(){
movies = new ArrayList<>();
}
public interface OnPosterClickListener{
void OnPosterClick(int position);
}
public interface OnReachEndListener{
void onReachEnd();
}
public interface onStartLoadingListener{
void onStartLoading();
}
public void setOnStartLoadingListener(onStartLoadingListener onStartLoadingListener) {
this.onStartLoadingListener = onStartLoadingListener;
}
public void setOnPosterClickListener(OnPosterClickListener onPosterClickListener) {
this.onPosterClickListener = onPosterClickListener;
}
public void setOnReachEndListener(OnReachEndListener onReachEndListener) {
this.onReachEndListener = onReachEndListener;
}
@NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_item, parent, false);
return new MovieViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
if (movies.size() >= 20 && position > movies.size() - 4 && onReachEndListener != null){
onReachEndListener.onReachEnd();
}
Movie movie = movies.get(position);
Picasso.get().load(movie.getPosterPath()).into(holder.imageViewSmallPoster);
}
@Override
public int getItemCount() {
return movies.size();
}
class MovieViewHolder extends RecyclerView.ViewHolder{
private ImageView imageViewSmallPoster;
public MovieViewHolder(@NonNull View itemView) {
super(itemView);
imageViewSmallPoster = itemView.findViewById(R.id.imageViewSmallPoster);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(onPosterClickListener != null){
onPosterClickListener.OnPosterClick(getAdapterPosition());
}
}
});
}
}
public void clear(){
this.movies.clear();
notifyDataSetChanged();
}
public List<Movie> getMovies() {
return movies;
}
public void addMovies(List<Movie> movies){
this.movies.addAll(movies);
notifyDataSetChanged();
}
public void setMovies(List<Movie> movies) {
this.movies = movies;
notifyDataSetChanged();
}
}