Reputation: 407
I have an app where I am retrieving movie posters from an API in an AsyncTask. I need to display top_rated and popular movies. Thus, I have popular and Top rated in my options menu. On opening the app, it loads (20) popular movies via AsyncTask. The issue now is on clicking either of popular or top rated in my options menu, it adds the newly fetched (20) posters to the (20) ones on the UI already (making it 40 movies now) instead of clearing the ones on the screen and replacing with the newly fetched 20 movie posters.
I have tried calling notifyDataSetChanged()
on the adapter. Also, I tried calling a new AsyncTask for each options clicked, neither worked. I have tried options on this thread but to no avail.
Here is my code:
package com.quwaysim.popularmovies.ui;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.quwaysim.popularmovies.MovieAdapter;
import com.quwaysim.popularmovies.R;
import com.quwaysim.popularmovies.model.MovieDetails;
import com.quwaysim.popularmovies.utils.NetworkUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
MovieAdapter mAdapter;
ArrayList<MovieDetails> mMovieList = new ArrayList<>();
ProgressBar mProgressBar;
String api = "popular";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = findViewById(R.id.progressBar);
mRecyclerView = findViewById(R.id.movies_rv);
fetchMovies(api);
}
public void fetchMovies(String api) {
URL apiURL = NetworkUtils.buildUrl(api);
new FetchMovie().execute(apiURL);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sort_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.popular:
Toast.makeText(this, "Popular", Toast.LENGTH_SHORT).show();
// Trying my options here
URL popular = NetworkUtils.buildUrl("popular");
new FetchMovie().execute(popular);
mAdapter.notifyDataSetChanged();
return true;
case R.id.top_rated:
Toast.makeText(this, "Top Rated", Toast.LENGTH_SHORT).show();
// Trying my options here
URL topRated = NetworkUtils.buildUrl("top_rated");
new FetchMovie().execute(topRated);
mAdapter.notifyDataSetChanged();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public class FetchMovie extends AsyncTask<URL, Void, String> {
private final String TAG = "FetchMovieAsyncTask";
private int mNoOfMovies;
@Override
protected void onPreExecute() {
mProgressBar.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected String doInBackground(URL... urls) {
URL url = urls[0];
String movieResults = null;
try {
movieResults = NetworkUtils.getResponseFromUrl(url);
} catch (IOException e) {
Log.d(TAG, "doInBackground: " + e);
}
return movieResults;
}
@Override
protected void onPostExecute(String s) {
if (s != null && !s.equals("")) {
mProgressBar.setVisibility(View.INVISIBLE);
try {
JSONObject parsedMoviesJSON = new JSONObject(s);
JSONArray moviesArray = parsedMoviesJSON.getJSONArray("results");
mNoOfMovies = moviesArray.length();
moviesArray.getString(1);
for (int i = 0; i < mNoOfMovies; i++) {
MovieDetails mMovDetails = new MovieDetails();
String details = moviesArray.get(i).toString();
JSONObject detailsParsed = new JSONObject(details);
mMovDetails.setMoviePoster("http://image.tmdb.org/t/p/w185/"
+ detailsParsed.getString("poster_path"));
mMovieList.add(mMovDetails);
Log.d(TAG, "onPostExecute: forLoop" + mMovDetails.getMoviePoster());
}
} catch (JSONException e) {
Log.d(TAG, "onPostExecute: error => " + e);
e.printStackTrace();
}
Log.d("TAG", "onPostExecute: movieList" + mMovieList);
mAdapter = new MovieAdapter(mMovieList);
mRecyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this, 2));
mRecyclerView.setAdapter(mAdapter);
Log.d(TAG, "onPostExecute: it's a success " + mNoOfMovies);
}
}
}
}
The NetworkUtils class is just for opening connection and building the full api URL. I didn’t include it here because I want to keep this post as short as possible. Please let me know if you need anything. Thanks in advance.
Upvotes: 0
Views: 43
Reputation: 4035
Yes this happens because you are using the same list object on and on, you must create a new list before using it in onPostExecute() add this:
mMovieList = new ArrayList<>();
directly above the for loop, like this:
//create a new list for each query
mMovieList = new ArrayList<>();
for (int i = 0; i < mNoOfMovies; i++) {
MovieDetails mMovDetails = new MovieDetails();
String details = moviesArray.get(i).toString();
....
....
....
GoodLuck.
Upvotes: 1