Search code examples
androidandroid-recyclerviewcustom-model-binder

RecyclerView works with custom object when I add it to the list manually, but not when I instantiate it with data from RESTful service


I'm working on a project in Android Studio were I would need to list several movies in a RecyclerView (in this case from RESTful API several means 20). Now I have set everything up and my static dummy content is displayed within recyclerview using cardview. Nevertheless, I have issues with my real data (from RESTful API) when I switch to it. Here is my MainActivity.java code WITH manual data (when data is displayed):

public class MainActivity extends RecyclerViewActivity {

private static List<Film> listFilm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setLayoutManager(new LinearLayoutManager(this));
    setAdapter(new FilmAdapter());

    listFilm = new ArrayList<>();

    listFilm.add(new Film("Star Wars", "Princess Leia is captured and held hostage by the evil Imperial forces in their effort to take over the galactic Empire. Venturesome Luke Skywalker and dashing captain Han Solo team together with the loveable robot duo R2-D2 and C-3PO to rescue the beautiful princess and restore peace and justice in the Empire."));
    listFilm.add(new Film("E.T. the Extra-Terrestrial", "A science fiction fairytale about an extra-terrestrial who is left behind on Earth and is found by a young boy who befriends him. This heart-warming fantasy from Director Steven Spielberg became one of the most commercially successful films of all time."));
    listFilm.add(new Film("Jurassic Park", "A wealthy entrepreneur secretly creates a theme park featuring living dinosaurs drawn from prehistoric DNA. Before opening day, he invites a team of experts and his two eager grandchildren to experience the park and help calm anxious investors. However, the park is anything but amusing as the security systems go off-line and the dinosaurs escape."));
    listFilm.add(new Film("The Lion King", "A young lion cub named Simba can't wait to be king. But his uncle craves the title for himself and will stop at nothing to get it."));
    listFilm.add(new Film("Independence Day", "On July 2, a giant alien mothership enters orbit around Earth and deploys several dozen saucer-shaped 'destroyer' spacecraft that quickly lay waste to major cities around the planet. On July 3, the United States conducts a coordinated counterattack that fails. On July 4 the a plan is devised to gain access to the interior of the alien mothership in space in order to plant a nuclear missile."));
    listFilm.add(new Film("Titanic", "84 years later, a 101-year-old woman named Rose DeWitt Bukater tells the story to her granddaughter Lizzy Calvert, Brock Lovett, Lewis Bodine, Bobby Buell and Anatoly Mikailavich on the Keldysh about her life set in April 10th 1912, on a ship called Titanic when young Rose boards the departing ship with the upper-class passengers and her mother, Ruth DeWitt Bukater, and her fiancé, Caledon Hockley. Meanwhile, a drifter and artist named Jack Dawson and his best friend Fabrizio De Rossi win third-class tickets to the ship in a game. And she explains the whole story from departure until the death of Titanic on its first and last voyage April 15th, 1912 at 2:20 in the morning."));
    listFilm.add(new Film("Star Wars: Episode I - The Phantom Menace", "Anakin Skywalker, a young slave strong with the Force, is discovered on Tatooine. Meanwhile, the evil Sith have returned, enacting their plot for revenge against the Jedi."));
    listFilm.add(new Film("Harry Potter and the Philosopher's Stone", "Harry Potter has lived under the stairs at his aunt and uncle's house his whole life. But on his 11th birthday, he learns he's a powerful wizard -- with a place waiting for him at the Hogwarts School of Witchcraft and Wizardry. As he learns to harness his newfound powers with the help of the school's kindly headmaster, Harry uncovers the truth about his parents' deaths -- and about the villain who's to blame."));
    listFilm.add(new Film("The Lord of the Rings: The Fellowship of the Ring", "Young hobbit Frodo Baggins, after inheriting a mysterious ring from his uncle Bilbo, must leave his home in order to keep it from falling into the hands of its evil creator. Along the way, a fellowship is formed to protect the ringbearer and make sure that the ring arrives at its final destination: Mt. Doom, the only place where it can be destroyed."));
    listFilm.add(new Film("Spider-Man", "After being bitten by a genetically altered spider, nerdy high school student Peter Parker is endowed with amazing powers."));

}

Adapter for Movie model is:

private class FilmAdapter extends RecyclerView.Adapter<RowHolder> {

    Context context;

    public Context getContext() {
        return this.context;
    }

    @Override
    public RowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new RowHolder(getLayoutInflater().inflate(R.layout.row, parent, false));
    }

    @Override
    public void onBindViewHolder(RowHolder holder, int position) {
        Film movie = listFilm.get(position);

        TextView title   = holder.title;
        title.setText(movie.getTitle());
        TextView desc    = holder.desc;
        desc.setText(movie.getDescription());
        ImageView poster = holder.poster;
        Picasso.with(getApplicationContext()).load("http://cdn2-www.comingsoon.net/assets/uploads/2015/03/avengersorder5.jpg").into(poster);
    }

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

And ViewHolder class is:

private class RowHolder extends RecyclerView.ViewHolder {

    TextView  title  = null;
    TextView  desc   = null;
    ImageView poster = null;

    public RowHolder(View itemView) {
        super(itemView);

        title  = (TextView)  itemView.findViewById(R.id.title);
        desc   = (TextView)  itemView.findViewById(R.id.desc);
        poster = (ImageView) itemView.findViewById(R.id.poster);
    }

}

When contacting my RESTful API MainActivity.java looks like:

public class MainActivity extends RecyclerViewActivity {

private static List<Film> listFilm;
public static final String apiURL = "https://api.themoviedb.org/4/list/10?page=1&api_key=8e20230f25939a349c2e37680cdaff95&sort_by=release_date.asc";
private JSONObject jsonObject;
private JSONArray  jsonArray;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setLayoutManager(new LinearLayoutManager(this));
    setAdapter(new FilmAdapter());

    listFilm = new ArrayList<>();

    RequestQueue queue = Volley.newRequestQueue(this);

    StringRequest stringRequest = new StringRequest(Method.GET, apiURL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    Toast.makeText(getApplicationContext(), "RADI", Toast.LENGTH_SHORT).show();

                    try {


                        jsonObject = new JSONObject(response);
                        jsonArray  = jsonObject.getJSONArray("results");
                        int i = 0;

                        while(i < jsonArray.length()) {
                            JSONObject movie = jsonArray.getJSONObject(i);

                            Film movieInstance = new Film(movie.getString("original_title"), movie.getString("overview"), "https://image.tmdb.org/t/p/w500" + movie.getString("backdrop_path"));
                            listFilm.add(movieInstance);
                            i ++ ;
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Toast.makeText(getApplicationContext(), "NE RADI", Toast.LENGTH_SHORT).show();
        }
    });

}

The rest is the same in both cases. I logged everything several times, the data is valid everything is fine list is filled with 20 movies all corresponding from the API. So any thoughts? To summarize in the first case I have the app working fine, and in the latter no data is shown. Anyone knows or had a similar issue? Thank you in advance.


Solution

  • You have to let the adapter know that you changed the data. It will notify the attached recycler and it will update its views.

    After the loop where you add items from the api, add this:

    adapter.notifyDataSetChanged();
    

    In the first example you don't need this because at the time the recycler does its initial layout (after onCreate), the content is already there.