1

i am using volley to make REST API requests to tmdb database for loading information about movies. The recycler view should display thumbnail image posters. But it is not displaying anything. i am using picasso library to load images. the image links are constructed fine, which i have checked with log statement

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.android.moviesapp.MainActivity">
    <android.support.v7.widget.RecyclerView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/movierecyclerview">
    </android.support.v7.widget.RecyclerView>
</RelativeLayout>

list_item_layout.xml

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

MainActivity

package com.example.android.moviesapp;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

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

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;


public class MainActivity extends AppCompatActivity {

    private ArrayList<HashMap<String, String>> movies = new ArrayList<>();
    private ArrayList<String> moviePosters = new ArrayList<>();

    final static String POSTER_PATH = "poster_path";
    final static String TITLE = "title";
    final static String VOTE_COUNT = "vote_count";
    final static String VOTE_AVERAGE = "vote_average";
    final static String OVERVIEW = "overview";
    final static String RELEASE_DATE ="release_date";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final MoviesAdapter adapter = new MoviesAdapter(getApplicationContext(), moviePosters);

        RecyclerView moviesRecyclerView = (RecyclerView) findViewById(R.id.movierecyclerview);
        moviesRecyclerView.setAdapter(adapter);
        moviesRecyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(), 2));

       try {

           final String BASE_URL =
                   "https://api.themoviedb.org/3/movie/";
           final String movieOrder = "popular";
           final String APPID = /* API KEY HERE */;

           Uri builtUri = Uri.parse(BASE_URL).buildUpon().appendPath(movieOrder).appendQueryParameter("api_key",APPID).build();

           URL url = new URL(builtUri.toString());

            JsonObjectRequest movieRequest = new JsonObjectRequest(Request.Method.GET, url.toString(), null, new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    try {


                        JSONArray results = response.getJSONArray("results");

                        Log.d ("DEBUG", response.toString());
                        for (int i = 0; i < results.length(); i++) {

                            JSONObject movieJSON = results.getJSONObject(i);
                            HashMap<String, String> movie = new HashMap<>();
                            movie.put(POSTER_PATH,movieJSON.getString(POSTER_PATH));
                            movie.put(TITLE,movieJSON.getString(TITLE));
                            movie.put(VOTE_COUNT,movieJSON.getString(VOTE_COUNT));
                            movie.put(VOTE_AVERAGE, movieJSON.getString(VOTE_AVERAGE));
                            movie.put(OVERVIEW, movieJSON.getString(OVERVIEW));
                            movie.put(RELEASE_DATE, movieJSON.getString(RELEASE_DATE));
                            movies.add(movie);
                        }
                    }
                    catch (JSONException e) {
                        Log.d ("DEBUG", "JSON exception");
                    }

                    for (HashMap<String, String> movie:movies) {
                        moviePosters.add(movie.get(POSTER_PATH));
                        adapter.notifyDataSetChanged();
                    }
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.d ("DEBUG","Network Error");
                }
            });

           RequestQueue mRequestQueue = MovieDataLoader.getSingletonInstance(this.getApplicationContext()).getRequestQueue();


            mRequestQueue.add(movieRequest);
        }
        catch (MalformedURLException e) {
            Log.d("DEBUG", "url not formed correctly");
        }



    }

    public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {

        private ArrayList<String> movies;
        private Context mContext;

        public class MoviesViewHolder extends RecyclerView.ViewHolder {

            public ImageView mImageView;

            public MoviesViewHolder (View itemView) {
                super(itemView);
                mImageView = (ImageView) itemView.findViewById(R.id.movie_poster_imageview);
            }

        }

        public MoviesAdapter(Context context, ArrayList<String> movies) {
            this.movies = movies;
            mContext = context;
        }

        @Override
        public MoviesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View moviesView = inflater.inflate(R.layout.list_item_layout,parent,false);
            return new MoviesViewHolder(moviesView);

        }

        @Override
        public int getItemCount() {
            return movies.size();
        }

        @Override
        public void onBindViewHolder(MoviesViewHolder holder, int position) {
            String moviePosterPath = movies.get(position);
            final String BASE_URL = " http://image.tmdb.org/t/p/";
            final String IMAGE_SIZE = "w185";

            Uri posterPath = Uri.parse(BASE_URL).buildUpon().appendPath(IMAGE_SIZE).appendEncodedPath(moviePosterPath).build();
            Log.d("DEBUG",posterPath.toString());
            picasso.with(mContext).load(posterPath.toString()).into(holder.mImageView);

        }
    }
}

MovieDataLoader

package com.example.android.moviesapp;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.LruCache;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;

public class MovieDataLoader {

    private static MovieDataLoader mSingletonInstance;
    private RequestQueue mRequestQueue;
    private static Context mCtx;

    private MovieDataLoader(Context ctx) {
        mCtx = ctx;
        mRequestQueue = getRequestQueue();

    }

    public static synchronized MovieDataLoader getSingletonInstance(Context ctx) {
        if (mSingletonInstance == null) {
            mSingletonInstance = new MovieDataLoader(ctx);
        }
        return mSingletonInstance;
    }

    public RequestQueue getRequestQueue() {
        if(mRequestQueue == null) {

            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }


}
Bharat
  • 386
  • 5
  • 20
  • follow this http://stackoverflow.com/questions/25744344/android-picasso-load-image-failed-how-to-show-error-message to log the picasso error message and edit the questions with the logs please – Ahmed Abidi Jan 30 '17 at 16:23
  • How did you save your images in the database , did you save just a single photo like flower.png or with a link http:/Images/flower.png – Lutaaya Huzaifah Idris Jan 30 '17 at 16:30
  • @LutaayaHuzaifahIdris i am not saving the images any where... i am just loading them using picasso library into the image view – Bharat Jan 30 '17 at 16:42
  • @AhmedAbidi I have added listener as mentioned in the question you suggested, the logs are not displaying anything – Bharat Jan 30 '17 at 16:44
  • @BharatMukkala Run your application in [Debug mode](http://stackoverflow.com/questions/17677506/android-studio-open-debug-mode-when-app-is-running) and set breakpoints at critical points. – Gurupad Mamadapur Jan 30 '17 at 17:52
  • @BharatMukkala, so you mean you dont have a server or database anywhere? , ve not got you wery well – Lutaaya Huzaifah Idris Jan 30 '17 at 19:30
  • If the code is hosted on github, post the link, I'm curious to find the bug. – Gurupad Mamadapur Jan 30 '17 at 20:18
  • @GurupadMamadpur i have hosted it in github at https://github.com/bharatmukkala/moviesp Thanks, and you have put TMDB API key in Main Activity in order for it to work – Bharat Jan 31 '17 at 01:43

1 Answers1

2

I'm going to point out where the bugs are lying and how you can find them.

  • Read the logs carefully and you'll see an error related to permissions
  • Inspect the code in onBindViewHolder by adding break points and running in debug mode. There is a problem with some constant.
  • Check your activity_main.xml, especially the attributes of RecyclerView.

Proceed ahead only if you couldn't find those.


  • You need to add uses - INTERNET permission in the manifest.xml.
  • There is an extra leading space in the BASE_URL. Remove it.
  • Change wrap_content to match_parent.

Also, you shouldn't add listeners in that way. You've should implement them in the MainActivity.class itself, so that you need not declare adapter variable as final. Check the pull request here.

Community
  • 1
  • 1
Gurupad Mamadapur
  • 989
  • 1
  • 13
  • 24
  • @GurupadMamadpur Thanks for the answer. should we change the attribute of recycler view because it is initially empty, so it doesn't have any content ? – Bharat Feb 01 '17 at 15:07
  • @BharatMukkala Happy to help. I'm not sure what the root cause is, I think `GridLayoutManager` will not be able to measure width & height if set to wrap_content. Looks like there have been some bug fixes and problems related to it - [1](http://stackoverflow.com/questions/26649406/nested-recycler-view-height-doesnt-wrap-its-content), [2](http://stackoverflow.com/questions/36382391/recycler-view-item-fill-up-entire-recycler-view-height-after-upgrading-support-l) & [3](http://stackoverflow.com/questions/35619022/nullpointerexception-in-dissapearence-animation-of-recyclerview-from-support-v-2). – Gurupad Mamadapur Feb 01 '17 at 16:26