Picasso Images are not loading in Gridview Android

2019-02-15 02:18发布

问题:

I have been making a Movie App (project work for learning android on udacity btw). I encountered a few problems but resolved them by following threads such as these Unable to modify ArrayAdapter in ListView: UnsupportedOperationException

However, although my app does not crash, the images are not loading and I cannot figure out why. Here is my code:

Layout XMl files movies_item.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id = "@+id/movies_item_thumbnail"
    >
</ImageView>

fragment_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.example.cindy.popularmovies.MoviesFragment">

    <GridView
        android:id="@+id/movies_gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="auto_fit"
        android:gravity="center"
        />

</FrameLayout>

MovieArrayAdapter.java

    public class MovieArrayAdapter extends ArrayAdapter<Movie> {
        private final Context context;
        private final List<Movie> movies;

        public MovieArrayAdapter(Context context,List<Movie> movies) {
            super(context,0,movies);
            this.context = context;
            this.movies = movies;
        }

        /*
        * Within the getView() method you would inflate an XML based layout and
        * then set the content of the individual views based on the Java object for this row.
        * */

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            View rowView = convertView;
            if(rowView == null) {
                //Inflate the XML based Layout
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                rowView = inflater.inflate(R.layout.movies_item, parent, false);

                //Get the ImageView
                ImageView movieThumbnail = (ImageView) rowView.findViewById(R.id.movies_item_thumbnail);


                //Load Image into the ImageView
                Picasso.with(context).load(movies.get(position).getThumbnail()).into(movieThumbnail);

                Log.v("Populating", movies.get(position).getThumbnail());
            }
            return rowView;
        }

        @Override
        public int getCount() {
            return super.getCount();
        }

        @Override
        public int getPosition(Movie item) {
            return super.getPosition(item);
        }
    }


MovieFragment.java

public class MoviesFragment extends Fragment {

    private MovieArrayAdapter mMoviesAdapter;

    public MoviesFragment() {
    }

    @Override
    public void onStart() {
        super.onStart();
        new FetchMoviesTask().execute();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        mMoviesAdapter = new MovieArrayAdapter(getActivity(),new ArrayList<Movie>());

        GridView moviesGridView = (GridView) rootView.findViewById(R.id.movies_gridview);
        moviesGridView.setAdapter(mMoviesAdapter);

        return rootView;
    }

    public class FetchMoviesTask extends AsyncTask<String,Void,Movie[]> {

        final String LOG_TAG = this.getClass().getSimpleName();

        @Override
        protected Movie[] doInBackground(String...params) {

            //Retrieve the Popular Movies Json String
            String moviesJsonString = getMoviesJsonString();

            //Parse the Json String to get important data
            try {
                return getPopularMoviesInfo(moviesJsonString);
            } catch(JSONException e) {
                Log.e(LOG_TAG,e.getMessage(),e);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Movie[] movies) {
            if(movies != null) {
                mMoviesAdapter.clear();
                mMoviesAdapter.addAll(movies);
            }
        }

        /*
                * This Function is to retrieve the Popular movies Json String from a WEB API
                * */
        private String getMoviesJsonString() {
            HttpURLConnection urlConnection = null;
            BufferedReader bufferedReader = null;
            String moviesJsonString = null;

            try {

                //Set up the URI
                final String MOVIES_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
                final String SORT_PARAM = "sort_by";
                final String API_PARAM ="api_key";

                Uri moviesUri = Uri.parse(MOVIES_BASE_URL).buildUpon()
                        .appendQueryParameter(SORT_PARAM, "popularity.desc")
                        .appendQueryParameter(API_PARAM,getString(R.string.movies_api))
                        .build();

                //Open the connection
                URL url = new URL(moviesUri.toString());
                urlConnection = (HttpURLConnection)url.openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                //Read the input stream into a string
                InputStream inputStream = urlConnection.getInputStream();
                if(inputStream == null) {
                    return null;
                }

                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

                String line;
                StringBuffer buffer = new StringBuffer();
                while((line = bufferedReader.readLine()) != null) {
                    buffer.append(line + "\n");
                }

                if(buffer.length() == 0){
                    //Stream was empty
                    return null;
                }

                moviesJsonString = buffer.toString();

            }catch(IOException e) {
                Log.e(LOG_TAG,"Error",e);
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                if(bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch(IOException e) {
                        Log.e(LOG_TAG, "Error closing stream", e);
                    }
                }
            }

            return moviesJsonString;
        }

        /*
        * This function is to parse the JSON String to retrieve info
        * */
        private Movie[] getPopularMoviesInfo(String jsonString) throws JSONException{

            //Base URL of thumbnail
            final String THUMBNAIL_BASE_URL = " http://image.tmdb.org/t/p/w185";

            //The attribute names we are interested in the JSON String
            final String M_RESULTS = "results";
            final String M_THUMBNAIL = "backdrop_path";
            final String M_TITLE = "original_title";
            final String M_ID = "id";
            final String M_SYPNOSIS = "overview";
            final String M_USER_RATING = "vote_average";
            final String M_RELEASE_DATE = "release_date";


            //Convert Json String to Json Object
            JSONObject moviesJsonObject = new JSONObject(jsonString);

            //Get the Json Array
            JSONArray moviesJsonArray = moviesJsonObject.getJSONArray(M_RESULTS);

            Movie[] movies = new Movie[moviesJsonArray.length()];
            for(int i=0;i<moviesJsonArray.length();i++) {
                JSONObject movie = moviesJsonArray.getJSONObject(i);

                movies[i] = new Movie(THUMBNAIL_BASE_URL + movie.getString(M_THUMBNAIL),
                                    movie.getString(M_TITLE),
                                    movie.getString(M_ID),
                                    movie.getString(M_SYPNOSIS),
                                    movie.getString(M_USER_RATING),
                                    movie.getString(M_RELEASE_DATE));

                Log.v("Movie",movie.getString(M_TITLE));
            }

            return movies;

        }
    }
}

There is no error, but the images are not loading. I have been looking in other threads, but cannot find the answer to my problem. Thank you very much.

[UPDATED] Changed the code according to discussion below:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if(convertView == null) {
            //Inflate the XML based Layout
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.movies_item, parent, false);
        }

        //Get the ImageView
        ImageView movieThumbnail = (ImageView) convertView.findViewById(R.id.movies_item_thumbnail);

        //Load Image into the ImageView
        Picasso.with(context).load(movies.get(position).getThumbnail()).into(movieThumbnail);

        Log.v("Populating", movies.get(position).getThumbnail());

        return convertView;
    }

回答1:

those line:

//Get the ImageView
ImageView movieThumbnail = (ImageView) rowView.findViewById(R.id.movies_item_thumbnail);

 //Load Image into the ImageView
 Picasso.with(context).load(movies.get(position).getThumbnail()).into(movieThumbnail);

go outside the if(rowView == null) {

You will always get only one null convertView, and you have to call that two lines while you are updating/populating your GridView . At the moment you should see alway the first image over and over. Please don't forget to add the Internet permission to the manifest