类似的问题已经回答here,但在我的案例中没有一个解决方案有帮助。
我尝试使用Retrofit获取电影评论数据,然后使用它来填充我的RecyclerView。
首先我得到一个回复,然后保存在 MovieReviewsList
中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();
}
}
这个类只存储一个MovieReviews列表。
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;
}
然后我试图在我的活动中显示该数据。但每次我运行我的应用程序时,我都会 没有附加适配器;跳过布局错误 。
这是我的活动:
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();
}
}
我已经记录了很多次,并确保我的网络呼叫始终返回数据。然后我在我的onResponse回调中设置了我的适配器中的数据。
以下是我的适配器的代码:
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();
}
}
记录错误:
02-21 10:21:31.708 17295-17295/com.example.android.popularmovies E/RecyclerView: No adapter attached; skipping layout
我已阅读this post which is on the same topic,但我还没有找到解决方案。
任何帮助将不胜感激。谢谢!
答案 0 :(得分:1)
private RecyclerView movieReviewsRecyclerView;
private RecyclerView reviewReviewsRecyclerView;
尝试使用适配器声明此参数,然后调用
movieReviewsRecyclerView.setAdapter(adapter);
来自api电话的回复
答案 1 :(得分:0)
在改装电话的onResponse()
中执行此操作
@Override
public void onResponse(Call<MovieReviewsList> call,
Response<MovieReviewsList> response) {
movieReviewsAdapter.setData(response.body());
}
并在您的适配器中(您应该这样做)
public void setData(MovieReviewsList movieReviewsList) {
this.reviewsList = movieReviewsList.getMovieReviewsList() ;
notifyDataSetChanged();
}
这是因为您正在使用 POJO OBJECT
初始化Java Collections.List更新: - 您正在执行此操作...而不是上述过程......(您在做什么)
public void setData(MovieReviewsList movieReviewsList) {
this.reviewsList = movieReviewsList;
notifyDataSetChanged();
}
答案 2 :(得分:0)
经过几天的调试后,我发现问题导致我的布局中出现数据绑定。我不知道到底出了什么问题,但我可以告诉我,当我删除数据绑定并使用Butter Knife来填充我的视图时,我不会再出现任何日志错误,并且我的活动按预期工作。
这是我的数据绑定布局:
<?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>
删除数据绑定后的布局:
<?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>
我仍然没有明确答案为什么会发生这种情况,但至少代码现在有效。
答案 3 :(得分:0)
在适配器代码中进行一些更改。
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);
}
}
然后在你得到api响应之后将时间放在代码之下..
movieReviewsAdapter = new MovieReviewsAdapter(response.body().getMovieReviewsList());
movieReviewsRecyclerView.setAdapter(movieReviewsAdapter);