0

A similar question has already been answered here, but none of the solutions helped in my case.

I'm trying to get movie reviews data using Retrofit and then using it to populate my RecyclerView.

First I get a response which is then saved in my MovieReviewsList

Code for MovieReviewsList:

import com.google.gson.annotations.SerializedName;
import java.util.List;

public class MovieReviewsList {
    @SerializedName("results")
    private final List<MovieReview> movieReviewsList;


    public MovieReviewsList(List<MovieReview> movieReviewsList) {
        this.movieReviewsList = movieReviewsList;
    }

    public List<MovieReview> getMovieReviewsList() {
        return movieReviewsList;
    }

    public int size() {
        return movieReviewsList.size();
    }
}

This class just stores a List of MovieReviews.

Code for MovieReviews:

    import com.google.gson.annotations.SerializedName;

    public class MovieReview {
        @SerializedName("author")
        private final String movieReviewAuthor;
        @SerializedName("url")
        private final String movieReviewUrl;


        public MovieReview(String movieReviewAuthor, String movieReviewUrl) {
            this.movieReviewAuthor = movieReviewAuthor;
            this.movieReviewUrl = movieReviewUrl;
        }

        public String getMovieReviewAuthor() {
            return movieReviewAuthor;
        }

        public String getMovieReviewUrl() {


     return movieReviewUrl;

}

Then I'm trying to display that data in my activity. But every time I run my app I get No adapter attached; skipping layout error.

Here is my activity:

import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.example.android.popularmovies.R;
import com.example.android.popularmovies.databinding.ActivityDetailBinding;
import com.example.android.popularmovies.network.movies.Movie;
import com.example.android.popularmovies.network.movies.MovieReview;
import com.example.android.popularmovies.network.movies.MovieReviewsList;
import com.example.android.popularmovies.network.movies.MovieTrailersList;
import com.example.android.popularmovies.network.MoviesClient;
import com.example.android.popularmovies.network.NetworkUtils;
import com.example.android.popularmovies.network.RetrofitInstance;
import com.google.gson.Gson;
import com.squareup.picasso.Picasso;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class DetailActivity extends AppCompatActivity {

    private static final String TAG = "DetailActivity";

    private MovieTrailersAdapter movieTrailersAdapter;
    private MovieReviewsAdapter movieReviewsAdapter;

    private Disposable movieTrailersCall;
    private Disposable movieReviewsCall;

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

        Intent launchingIntent = getIntent();
        if (launchingIntent == null || !launchingIntent.hasExtra(MainActivity.INTENT_EXTRA_MOVIE)) {
            finish();
        }
        String movieAsJson = launchingIntent.getStringExtra(MainActivity.INTENT_EXTRA_MOVIE);
        Movie movie = new Gson().fromJson(movieAsJson, Movie.class);

        // Trailers
        RecyclerView movieTrailersRecyclerView = findViewById(R.id.trailers_rv);
        LinearLayoutManager trailersLinearLayoutManager = new LinearLayoutManager(this);
        movieTrailersRecyclerView.setLayoutManager(trailersLinearLayoutManager);
        movieTrailersAdapter = new MovieTrailersAdapter();
        movieTrailersRecyclerView.setAdapter(movieTrailersAdapter);

        // Reviews
        RecyclerView movieReviewsRecyclerView = findViewById(R.id.reviews_rv);
        LinearLayoutManager reviewsLinearLayoutManager = new LinearLayoutManager(this);
        movieReviewsRecyclerView.setLayoutManager(reviewsLinearLayoutManager);
        movieReviewsAdapter = new MovieReviewsAdapter();
        movieReviewsRecyclerView.setAdapter(movieReviewsAdapter);

        // Network call
        getMovieTrailersAndReviews(movie);

        ActivityDetailBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_detail);
        Picasso.with(this)
                .load(NetworkUtils.getImageUrl(movie.getThumbnailPath()))
                .into(binding.thumbnailIv);
        binding.setMovie(movie);

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void getMovieTrailersAndReviews(Movie movie) {
        if (movie == null || !NetworkUtils.isConnectedToInternet(this)) {
            Toast.makeText(this, "Please connect to internet", Toast.LENGTH_SHORT).show();
            return;
        }
        Retrofit retrofit = RetrofitInstance.getRetrofitInstance();
        MoviesClient moviesClient = retrofit.create(MoviesClient.class);

        Call<MovieTrailersList> movieTrailersCall = moviesClient.getMovieTrailers(movie.getId(), NetworkUtils.API_KEY);
        movieTrailersCall.enqueue(new Callback<MovieTrailersList>() {
            @Override
            public void onResponse(Call<MovieTrailersList> call, Response<MovieTrailersList> response) {
                movieTrailersAdapter.setData(response.body());
            }

            @Override
            public void onFailure(Call<MovieTrailersList> call, Throwable t) {

            }
        });

        Call<MovieReviewsList> movieReviewsCall = moviesClient.getMovieReviews(movie.getId(), NetworkUtils.API_KEY);
        movieReviewsCall.enqueue(new Callback<MovieReviewsList>() {
            @Override
            public void onResponse(Call<MovieReviewsList> call, Response<MovieReviewsList> response) {
                movieReviewsAdapter.setData(response.body());
            }

            @Override
            public void onFailure(Call<MovieReviewsList> call, Throwable t) {

            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

I have logged a bunch of times and I have made sure that my network call always returns data. Then I set that data, inside of my onResponse callbacks, in my adapter.

Here is the code for my adapter:

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.android.popularmovies.R;
import com.example.android.popularmovies.network.movies.MovieReview;
import com.example.android.popularmovies.network.movies.MovieReviewsList;

public class MovieReviewsAdapter extends RecyclerView.Adapter<MovieReviewsAdapter.ViewHolder> {

    private static final String TAG = "MovieReviewsAdapter";

    private MovieReviewsList reviewsList;

    public MovieReviewsAdapter() { }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View containerView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.review_item, parent, false);
        return new ViewHolder(containerView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        MovieReview movieReview = reviewsList.getMovieReviewsList().get(position);
        holder.reviewedByTextView.setText(movieReview.getMovieReviewAuthor());
    }

    @Override
    public int getItemCount() {
        if (reviewsList == null) {
            return 0;
        }
        return reviewsList.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        final TextView reviewedByTextView;

        ViewHolder(View itemView) {
            super(itemView);
            reviewedByTextView = itemView.findViewById(R.id.review_by_tv);
        }
    }

    public void setData(MovieReviewsList movieReviewsList) {
        this.reviewsList = movieReviewsList;
        notifyDataSetChanged();
    }
}

Log errors:

02-21 10:21:31.708 17295-17295/com.example.android.popularmovies E/RecyclerView: No adapter attached; skipping layout

I have read this post which is on the same topic, but I haven't found a solution.

Any help would be appreciated. Thanks!

Vid Bregar
  • 148
  • 6
  • 3
    Possible duplicate of [recyclerview No adapter attached; skipping layout](https://stackoverflow.com/questions/29141729/recyclerview-no-adapter-attached-skipping-layout) – Abhishek kumar Feb 21 '18 at 09:43
  • If you mean that I am getting two **No adapter attached; skipping layout** log errors, you are correct. But that is since I am doing the same thing to get movie trailers. I didn't include that code since the implementation is the same. – Vid Bregar Feb 21 '18 at 10:00

4 Answers4

1
private RecyclerView movieReviewsRecyclerView;
private RecyclerView reviewReviewsRecyclerView;

Try declaring this paramaters as you have done for adapters and then call

movieReviewsRecyclerView.setAdapter(adapter);

on response from api call

Harsh Agrawal
  • 597
  • 3
  • 12
0

Do this in onResponse() of retrofit call

        @Override
        public void onResponse(Call<MovieReviewsList> call, 
                               Response<MovieReviewsList> response) {

        movieReviewsAdapter.setData(response.body());

        }

and in your adapter(you should do)

public void setData(MovieReviewsList movieReviewsList) {
    this.reviewsList = movieReviewsList.getMovieReviewsList() ;
    notifyDataSetChanged();
}

this is because you are initializing the Java Collections.List with POJO OBJECT

Update :- You are doing this...instead of the above process...(what are you doing)

public void setData(MovieReviewsList movieReviewsList) {
    this.reviewsList = movieReviewsList;
    notifyDataSetChanged();
}
Santanu Sur
  • 10,997
  • 7
  • 33
  • 52
0

After a few day of debugging, I have found out that the problem is causing data binding inside of my layout. I don't know exactly what is wrong, but I can tell that when I remove data binding and use Butter Knife to populate my views, I no longer get any log errors and my activity works as expected.

Here is my layout with data binding:

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="movie"
            type="com.example.android.popularmovies.network.movies.Movie" />
    </data>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:context="com.example.android.popularmovies.ui.DetailActivity">

            <ImageView
                android:id="@+id/thumbnail_iv"
                android:layout_width="0dp"
                android:layout_height="250dp"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:adjustViewBounds="true"
                android:contentDescription="@string/thumbnail_of_the_image"
                android:scaleType="fitCenter"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:src="@drawable/mad_max" />

            <TextView
                android:id="@+id/movie_title_tv"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:text="@{movie.title}"
                android:textColor="@android:color/black"
                android:textSize="30sp"
                android:textStyle="bold"
                app:layout_constraintBottom_toTopOf="@+id/thumbnail_iv"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/thumbnail_iv"
                app:layout_constraintTop_toBottomOf="@+id/thumbnail_iv"
                tools:text="Mad Max - Fury Road" />

            <TextView
                android:id="@+id/release_date_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:text="@{movie.releaseDate}"
                android:textSize="12sp"
                android:textStyle="italic"
                app:layout_constraintBaseline_toBaselineOf="@+id/released_label"
                app:layout_constraintStart_toEndOf="@+id/released_label"
                tools:text="May 14, 2015" />

            <TextView
                android:id="@+id/rating_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:text="@{movie.userRating}"
                android:textSize="14sp"
                android:textStyle="bold"
                app:layout_constraintBaseline_toBaselineOf="@+id/rating_label"
                app:layout_constraintStart_toEndOf="@+id/rating_label"
                tools:text="8/10" />

            <TextView
                android:id="@+id/rating_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/rating"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="@+id/released_label"
                app:layout_constraintTop_toBottomOf="@+id/released_label" />

            <TextView
                android:id="@+id/released_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:text="@string/released"
                app:layout_constraintStart_toStartOf="@+id/movie_title_tv"
                app:layout_constraintTop_toBottomOf="@+id/movie_title_tv" />

            <TextView
                android:id="@+id/description_tv"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="16dp"
                android:text="@{movie.plotSynopsis}"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/thumbnail_iv"
                tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit." />

            <View
                android:id="@+id/horizontal_line"
                android:layout_width="0dp"
                android:layout_height="1dp"
                android:layout_margin="8dp"
                android:background="@android:color/darker_gray"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/description_tv" />

            <TextView
                android:id="@+id/trailers_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:text="@string/trailers_label"
                android:textColor="@android:color/black"
                android:textSize="21sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/description_tv" />


            <android.support.v7.widget.RecyclerView
                android:id="@+id/trailers_rv"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/trailers_label" />

            <TextView
                android:id="@+id/reviews_label"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                android:text="@string/reviews_label"
                android:textColor="@android:color/black"
                android:textSize="21sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/trailers_rv" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/reviews_rv"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/reviews_label" />

        </android.support.constraint.ConstraintLayout>
    </android.support.v4.widget.NestedScrollView>
</layout>

My layout after removing data binding:

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context="com.example.android.popularmovies.ui.DetailActivity">

        <ImageView
            android:id="@+id/thumbnail_iv"
            android:layout_width="0dp"
            android:layout_height="250dp"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:adjustViewBounds="true"
            android:contentDescription="@string/thumbnail_of_the_image"
            android:scaleType="fitCenter"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:src="@drawable/mad_max" />

        <TextView
            android:id="@+id/movie_title_tv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:textColor="@android:color/black"
            android:textSize="30sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toTopOf="@+id/thumbnail_iv"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/thumbnail_iv"
            app:layout_constraintTop_toBottomOf="@+id/thumbnail_iv"
            tools:text="Mad Max - Fury Road" />

        <TextView
            android:id="@+id/release_date_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:textSize="12sp"
            android:textStyle="italic"
            app:layout_constraintBaseline_toBaselineOf="@+id/released_label"
            app:layout_constraintStart_toEndOf="@+id/released_label"
            tools:text="May 14, 2015" />

        <TextView
            android:id="@+id/rating_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:textSize="14sp"
            android:textStyle="bold"
            app:layout_constraintBaseline_toBaselineOf="@+id/rating_label"
            app:layout_constraintStart_toEndOf="@+id/rating_label"
            tools:text="8/10" />

        <TextView
            android:id="@+id/rating_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/rating"
            android:textStyle="bold"
            app:layout_constraintStart_toStartOf="@+id/released_label"
            app:layout_constraintTop_toBottomOf="@+id/released_label" />

        <TextView
            android:id="@+id/released_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/released"
            app:layout_constraintStart_toStartOf="@+id/movie_title_tv"
            app:layout_constraintTop_toBottomOf="@+id/movie_title_tv" />

        <TextView
            android:id="@+id/description_tv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/thumbnail_iv"
            tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit." />

        <View
            android:id="@+id/horizontal_line"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:layout_margin="8dp"
            android:background="@android:color/darker_gray"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/description_tv" />

        <TextView
            android:id="@+id/trailers_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:text="@string/trailers_label"
            android:textColor="@android:color/black"
            android:textSize="21sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/description_tv" />


        <android.support.v7.widget.RecyclerView
            android:id="@+id/trailers_rv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/trailers_label" />

        <TextView
            android:id="@+id/reviews_label"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"
            android:text="@string/reviews_label"
            android:textColor="@android:color/black"
            android:textSize="21sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/trailers_rv" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/reviews_rv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/reviews_label" />

    </android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>

I still don't have a clear answer as to why this is happening, but at least the code works now.

Vid Bregar
  • 148
  • 6
0

Make some changes in adapter code.

  private static final String TAG = "MovieReviewsAdapter";

private List<MovieReview> reviewsList;

public MovieReviewsAdapter(List<MovieReview> movieReviewsList) {
    this.reviewsList=movieReviewsList;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View containerView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.review_item, parent, false);
    return new ViewHolder(containerView);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    MovieReview movieReview = reviewsList.get(position);
    holder.reviewedByTextView.setText(movieReview.getMovieReviewAuthor());
}

@Override
public int getItemCount() {
    if (reviewsList == null) {
        return 0;
    }
    return reviewsList.size();
}

class ViewHolder extends RecyclerView.ViewHolder {
    final TextView reviewedByTextView;

    ViewHolder(View itemView) {
        super(itemView);
        reviewedByTextView = itemView.findViewById(R.id.review_by_tv);
    }
}

then after when you getting api response that time put below code..

 movieReviewsAdapter = new MovieReviewsAdapter(response.body().getMovieReviewsList());
    movieReviewsRecyclerView.setAdapter(movieReviewsAdapter);