2016-07-17 3 views
0

私にはわからない奇妙な問題があります。私のアプリは、ウェブサイト、特にポスター画像からムービーデータを取得します。私はRecyclerViewを作成しました。このRecyclerViewは、2列のグリッドにすべてのポスターを表示することになっています。RecyclerViewスクロール時にすべてのViewHoldersを作成してバインドします

スクロールの操作が非常に遅く、データリストに変更がなくても何らかの理由でアイテムがスクロール中にスワップしています。

私はアプリのデバッグを試みたが、最初の時間に私はnotifyDataSetChanged(呼び出すことが分かった)私のアダプタは(90回の周りに、ときにのみ6枚のポスターの私のリストにごとアイテムをonCreateViewHolder(...)を呼び出します任意の時点で可視です)、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; 
    } 

私は同様の質問見つかったこの質問を投稿しているのでEDIT

:私は固定値ではなく、「wrap_content」にlayout_height項目を設定したら、問題が固定され、実際にAndroid RecyclerView Creates and Binds all the views on Dataset change

を。どうやら、RecyclerViewはその高さを決定するためにすべてのビューを作成しようとしています。

しかし、私は、レイアウトマネージャのlm.setAutoMeasureEnabled(false)をlayout_heightを "wrap_content"に設定して呼び出し、問題を解決しないという問題を解決しました。この問題が発生していないのに、私はどのようにadaptiveな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リクエストごとにコードを追加して、あなたのソリューションを見て良いだろう。 –