2016-07-17 2 views
0

제가 지적 할 수없는 이상한 문제가 있습니다. 내 앱은 웹 사이트에서 영화 데이터, 특히 포스터 이미지를 가져옵니다. 필자는 RecyclerView를 만들었습니다.이 RecyclerView는 2 열 그리드의 모든 포스터를 표시합니다.RecyclerView 스크롤 할 때 모든 ViewHolders를 만들고 바인딩합니다.

스크롤링 환경이 지루하고, 데이터 목록에 변경 사항이 없는데도 항목이 중간 스크롤 위치를 바꿀 수 있습니다.

내가 응용 프로그램을 디버깅 시도하고, 내 어댑터가 내 목록에 모든 항목에 대한 onCreateViewHolder (...)를 호출 할 것이다) 처음에 나는 notifyDataSetChanged를 (전화 것을 알아 냈다 (약 90 배, 경우에만 6 개 포스터 주어진 순간에 볼 수 있습니다.) onBindViewAdapter (...)도 마찬가지입니다. 그런 다음 스크롤 할 때 모든 ViewHolders를 다시 만들고 다시 바인딩합니다!

나는 내 코드를 반복해서 확인 했으므로 그 원인을 파악하지 못했습니다. 귀하의 도움을 크게 주시면 감사하겠습니다.

RecyclerView.adapter :

public class MovieRecyclerViewAdapter extends RecyclerView.Adapter<MovieRecyclerViewAdapter.ViewHolder> { 
    private final Cinema cinema; 
    private final List<Movie> movies; 
    private final Context context; 
    private final DisplayMetrics displayMetrics; 
    private final Picasso picasso; 

    public MovieRecyclerViewAdapter(Context context, Cinema cinema, List<Movie> movies) { 
     this.context = context; 
     this.cinema = cinema; 
     this.movies = movies; 

     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     displayMetrics = new DisplayMetrics(); 
     wm.getDefaultDisplay().getMetrics(displayMetrics); 

     // Set up Picasso with okHttp3 
     okhttp3.OkHttpClient okHttp3Client = new okhttp3.OkHttpClient(); 
     OkHttp3Downloader okHttp3Downloader = new OkHttp3Downloader(okHttp3Client); 
     picasso = new Picasso.Builder(context) 
       .downloader(okHttp3Downloader) 
       .build(); 
    } 

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

    @Override 
    public void onBindViewHolder(final ViewHolder holder, int position) { 
     Movie movie = movies.get(position); 
     int imgViewWidth = displayMetrics.widthPixels/2; 
     int imgViewHeight = (int)(imgViewWidth * 1.4); 
     picasso.with(context) 
       .load(cinema.getPosterUrl(movie)) 
       .resize(imgViewWidth, imgViewHeight) 
       .into(holder.imageView); 
    } 

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

    public class ViewHolder extends RecyclerView.ViewHolder { 
     public ImageView imageView; 

     public ViewHolder(View view) { 
      super(view); 
      this.imageView = (ImageView) view.findViewById(R.id.fragment_movies_poster); 
     } 
    } 
} 

RecyclerView 항목 레이아웃 :

<?xml version="1.0" encoding="utf-8"?> 
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/fragment_movies_poster" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

</ImageView> 

RecyclerView의 XML 정의 :

<android.support.v7.widget.RecyclerView 
     android:id="@+id/fragment_movies_recycler_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:listitem="@layout/fragment_movies" /> 

RecyclerView 구성, 설정 어댑터 :

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_movies_grid, container, false); 

     Context context = view.getContext(); 
     RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.fragment_movies_recycler_view); 
     recyclerView.setLayoutManager(new GridLayoutManager(context, columnCount)); 
     movies = new ArrayList<>(); 
     adapter = new MovieRecyclerViewAdapter(context, cinema, movies); 
     recyclerView.setAdapter(adapter); 
     recyclerView.setHasFixedSize(true); 

     fetchMovies(view); // Populates movies list 

     return view; 
    } 

편집

내가 비슷한 질문 발견이 질문을 게시 이후 : 나는 오히려 "wrap_content"보다 고정 된 값으로 항목 layout_height를 설정하면, 실제로 Android RecyclerView Creates and Binds all the views on Dataset change

를 문제가 해결 . 분명히 RecyclerView는 높이를 결정하기 위해 모든 뷰를 생성하려고 시도합니다.

그러나이 질문에서 제공하는 솔루션을 시도했지만 layoutManager의 lm.setAutoMeasureEnabled(false)을 layout_height를 "wrap_content"로 설정하여 문제가 지속되었습니다. 이 문제가 발생하지 않는데 어떻게 적응 형 layout_height를 가질 수 있습니까?

답변

0

onMeasure()을 무시하고 너비에 따라 높이를 결정하는 고정 된 가로 세로 비율을 지정하여 항목에 대해 사용자 지정 ImageView 하위 클래스를 사용하여이 문제를 피할 수있었습니다.


FixedAspectRatioImageView : XML에 정의 된

public class FixedAspectRatioImageView extends ImageView{ 
    public FixedAspectRatioImageView(Context context) { 
     super(context); 
    } 

    public FixedAspectRatioImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public FixedAspectRatioImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
     int heightSize = (int) (widthSize * 1.4); 
     super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); 
    } 
} 

RecyclerView 항목 :

<?xml version="1.0" encoding="utf-8"?> 
<com.michaelsvit.kolnoa.FixedAspectRatioImageView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/fragment_movies_poster" 
    android:layout_width="match_parent" 
    android:layout_height="288dp"> // Value here does not matter, as it is dynamically set 
            // to be 1.4 times width 

</com.michaelsvit.kolnoa.FixedAspectRatioImageView> 
+0

은 여기 – Divers

+0

@Divers 귀하의 요청에 따라 코드를 추가 솔루션을 볼 좋을 것이다. –

관련 문제