The problem is i can't figure out why the grid won't filled with the images, the first time i run the app. If i do refresh or change to landscape mode the images load and the app works fine. I assume it has to be the List that i gave to the Adapter, somehow i lost his reference the first time and when the onCreateView calls again(refresh/landscape) it gets fixed. i tried to change the places where i define the adaptor, the list, etc and some methods too like setGridData but it doesn't work. Maybe you can help me
This is the code of the Fragment and the asynkTask(by the way it works fine).
public class MovieFragment extends Fragment {
private GridViewAdapter mGridViewAdapter;
private ArrayList<Movie> mMovieList = new ArrayList<Movie>();
public MovieFragment() {
}
@Override
public void onStart() {
super.onStart();
FetchMoviesTask movieTask = new FetchMoviesTask();
movieTask.execute("popular");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.moviefragment, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_refresh) {
FetchMoviesTask movieTask = new FetchMoviesTask();
movieTask.execute("popular");
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.moviefragment, container, false);
mGridViewAdapter = new GridViewAdapter(getActivity(),R.layout.movie_list_item, mMovieList);
GridView movieGrid= (GridView) rootView.findViewById(R.id.gridview_movie);
movieGrid.setAdapter(mGridViewAdapter);
return rootView;
}
public class FetchMoviesTask extends AsyncTask<String, Void, Movie[]> {
private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();
private Movie[] getMoviesDataFromJson(String moviesJsonStr) throws JSONException{
final String OMDB_RESULTS="results";
final String OMBD_POSTER_PATH="poster_path";
final String OMBD_RELEASE_DATE="release_date";
final String OMBD_OVERVIEW="overview";
final String OMBD_ORIGINAL_TITLE="original_title";
final String OMBD_VOTE_AVERAGE="vote_average";
final String url= "http://image.tmdb.org/t/p/";
final String imageSize="w185";
JSONObject moviesJson = new JSONObject(moviesJsonStr);
JSONArray moviesArray = moviesJson.getJSONArray(OMDB_RESULTS);
Movie[] results = new Movie[moviesArray.length()];
//CUIDADO ACA NO SE SI SE PASA POR UNO
for (int i=0; i<moviesArray.length();i++){
JSONObject movie=moviesArray.getJSONObject(i);
Movie index=new Movie();
index.setPoster_path(url+imageSize+movie.getString(OMBD_POSTER_PATH));
index.setOriginalTitle(movie.getString(OMBD_ORIGINAL_TITLE));
index.setOverview(movie.getString(OMBD_OVERVIEW));
index.setReleaseDate(movie.getString(OMBD_RELEASE_DATE));
index.setVoteAverage(movie.getDouble(OMBD_VOTE_AVERAGE));
results[i]=index;
}
return results;
}
@Override
protected Movie[] doInBackground(String... params) {
Movie[] imageMovies;
// If there's no zip code, there's nothing to look up. Verify size of params.
if (params.length == 0) {
return null;
}
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String moviesJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
final String MOVIE_BASE_URL =
"https://api.themoviedb.org/3/movie/"+params[0];
final String APPID_PARAM = "api_key";
Uri builtUri = Uri.parse(MOVIE_BASE_URL).buildUpon()
.appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_MOVIEDB_API_KEY)
.build();
URL url = new URL(builtUri.toString());
//Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
moviesJsonStr = buffer.toString();
imageMovies = getMoviesDataFromJson(moviesJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} catch (JSONException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return imageMovies;
}
@Override
protected void onPostExecute(Movie[] movies) {
if(movies!=null){
mGridViewAdapter.setGridData(Arrays.asList(movies));
}
}
}
}
And this is the code of the Adapter:
public class GridViewAdapter extends ArrayAdapter {
private static final String LOG_TAG = GridViewAdapter.class.getSimpleName();
private Context mContext;
private int mLayoutResourceId;
private ArrayList<Movie> mGridData;
/**
* This is our own custom constructor (it doesn't mirror a superclass constructor).
* The context is used to inflate the layout file, and the List is the data we want
* to populate into the lists
*
* @param context The current context. Used to inflate the layout file.
* @param movieList A List of AndroidFlavor objects to display in a list
*/
public GridViewAdapter(Activity context, int layoutResourceId, ArrayList<Movie> movieList) {
// Here, we initialize the ArrayAdapter's internal storage for the context and the list.
// the second argument is used when the ArrayAdapter is populating a single TextView.
// Because this is a custom adapter for two TextViews and an ImageView, the adapter is not
// going to use this second argument, so it can be any value. Here, we used 0.
super(context, layoutResourceId, movieList);
mContext=context;
mLayoutResourceId=layoutResourceId;
mGridData=movieList;
}
/**
* Updates grid data and refresh grid items.
*/
public void setGridData(List<Movie> movies) {
mGridData.clear();
mGridData.addAll(movies);
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageView imageView;
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(mLayoutResourceId, parent, false);
imageView = (ImageView) row.findViewById(R.id.list_item_movie_imageview);
row.setTag(imageView);
} else {
imageView = (ImageView) row.getTag();
}
Movie movie = mGridData.get(position);
Picasso.with(mContext).load(movie.getPoster_path()).into(imageView);
Log.d(LOG_TAG,movie.getOriginalTitle());
return row;
}
}
The movie class is a simple class with the data. The log in the getView() method pop up only once in the first run, but it has to be 20 times.