Search code examples
androidgridviewpicasso

Images are not loading in GridView using picasso 2.5.2


Currently I am developing a Popular Movies app by udacity and stuck at loading images from the MovieDb api. I have also took reference from this thread Picasso Images are not loading in Gridview Android but no use.

Here is my fragment file:

package com.akshitjain.popularmovies;

import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
ImageAdapter mMoviesAdapter;

public MainActivityFragment() {
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    final View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    GridView gridview = (GridView) rootView.findViewById(R.id.grid_view_movies);
    mMoviesAdapter = new ImageAdapter(getActivity());
    gridview.setAdapter(mMoviesAdapter);

    gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {
            Toast.makeText(getActivity(), "" + position,
                    Toast.LENGTH_SHORT).show();
        }
    });
    return rootView;
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_mainfragment,menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if(id == R.id.action_refresh){
        String sortOrder = "popularity.desc";
        new FetchMoviesTask().execute(sortOrder);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public class FetchMoviesTask extends AsyncTask<String, Void, String[]> {
    private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();

    private String[] getMoviesDataFromJson(String moviesJsonStr)
            throws JSONException {
        final String TMDB_RESULTS = "results";
        final String TMDB_POSTER = "poster_path";

        JSONObject moviesJson = new JSONObject(moviesJsonStr);
        JSONArray moviesArray = moviesJson.getJSONArray(TMDB_RESULTS);

        String[] resultStrs = new String[moviesArray.length()];
        for(int i=0;i<moviesArray.length();++i) {
            JSONObject movieObject = moviesArray.getJSONObject(i);
            resultStrs[i] = movieObject.getString(TMDB_POSTER);
        }
        return resultStrs;
    }

    @Override
    protected String[] doInBackground(String... params) {
        // 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;

        String apiKey = BuildConfig.THE_MOVIE_DB_API_KEY;

        try {
            // Construct the URL for the TheMovieDb query
            // Possible parameters are available at TheMovieDb API page
            final String MOVIES_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
            final String SORT_PARAM = "sort_by";
            final String API_KEY = "api_key";

            Uri builtUri = Uri.parse(MOVIES_BASE_URL).buildUpon()
                    .appendQueryParameter(SORT_PARAM,params[0])
                    .appendQueryParameter(API_KEY,apiKey)
                    .build();
            URL url = new URL(builtUri.toString());
            Log.v(LOG_TAG,"BuiltUri: " + builtUri.toString());

            // Create the request to TheMovieDb, and open the connection
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // Read the input stream into a String
            InputStream inputStream = urlConnection.getInputStream();
            StringBuilder buffer = new StringBuilder();
            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).append("\n");
            }

            if (buffer.length() == 0) {
                // Stream was empty.  No point in parsing.
                 return null;
            }
            moviesJsonStr = buffer.toString();
            Log.v(LOG_TAG,"Movies Json String: " + moviesJsonStr);
        } catch (IOException e) {
            Log.e("MainActivityFragment", "Error ", e);
            // If the code didn't successfully get the weather data, there's no point in attempting
            // to parse it.
            return null;
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e("MainActivityFragment", "Error closing stream", e);
                }
            }
        }

        try{
            return getMoviesDataFromJson(moviesJsonStr);
        }catch (JSONException e){
            Log.e(LOG_TAG,e.getMessage(),e);
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String[] strings) {
        if(strings != null){
            mMoviesAdapter.clear();
            for(String moviesStr:strings){
                mMoviesAdapter.add(moviesStr);
            }
        }
        mMoviesAdapter.notifyDataSetChanged();
        super.onPostExecute(strings);
    }
}
}

Here is my custom adapter file:

package com.akshitjain.popularmovies;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.List;


public class ImageAdapter extends BaseAdapter {
private final String LOG_TAG = ImageAdapter.class.getSimpleName();

private Context mContext;
List<String> list = new ArrayList<>();

public ImageAdapter(Context c) {
    this.mContext = c;
}

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

@Override
public Object getItem(int position) {
    return list.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(mContext).inflate(R.layout.grid_item_movies, parent, false);
    }

    final String POSTER_BASE_URL = " http://image.tmdb.org/t/p/";
    final String POSTER_SIZE = "w185";

    ImageView moviePoster = (ImageView) convertView.findViewById(R.id.grid_item_movie_image);
    final String POSTER_FINAL_URL = POSTER_BASE_URL + POSTER_SIZE + list.get(position);
    Log.v(LOG_TAG,"Poster Urls: " + POSTER_FINAL_URL);
    Picasso.with(mContext).load(POSTER_FINAL_URL).into(moviePoster);

    return convertView;
}

public void add(String s) {
    list.add(s);
}

public void clear() {
    list.clear();
}

}

There is no error in the code. App runs successfully. But images are not loading.


Solution

  • final String POSTER_BASE_URL = " http://image.tmdb.org/t/p/";
    

    The space at the beginning of the string was the issue. Picasso will try and load url with space at front. So String.trim() will remove the space from the beginning as well as the end of a String.

    Picasso.with(mContext).load(POSTER_FINAL_URL.trim()).into(moviePoster)