2015-09-13 54 views
1

我在使用CardViews時遇到問題。我創建了一個包含1個TextView和2個ImageView的CardView,並將其顯示在一個RecycleView中。當我嘗試更新其中一個CardViews的內容(創建了5個測試卡)時,界面在更新卡片上滾動時開始滯後,但當我通過該項目時恢復正常。它只發生在ImageViews存在的時候,當用ImageViews代替時,TextViews中有一些隨機文本,它正常工作。更新RecycleView中的CardView項目時遇到滯後

現在,這是我的代碼,之後我會添加一些可能導致它的信息。

首先,適配器類,其中也包含了項目類和List:

public class MovieDetailsAdapter extends RecyclerView.Adapter<MovieDetailsAdapter.MovieViewHolder> { 

public List<MovieDetails> movieList; 
private static final String TAG = "MyAdapter"; 

public MovieDetailsAdapter() { 

    movieList = new ArrayList< MovieDetails>(); 
} 




public void setItemCount(int count ,String title, Bitmap poster,Bitmap fanart) { 
    movieList.clear(); 
    movieList.addAll(generateDummyData(count, title, poster , fanart)); 

    notifyDataSetChanged(); 
} 


@Override 
public int getItemCount() { 

    return movieList.size(); 
} 


public void addItem(int position,String title, Bitmap poster, Bitmap fanart) { 
    if (position > movieList.size()) return; 

    movieList.add(position, generateDummyItem(title, poster, fanart)); 
    // notifyDataSetChanged(); 
    notifyItemInserted(position); 
} 

public void updateItem(int position, String title, Bitmap poster, Bitmap fanart) { 
    if (position > movieList.size()) return; 

    movieList.add(position, generateDummyItem(title, poster, fanart)); 
    notifyItemChanged(position); 
    // notifyDataSetChanged(); 
} 


@Override 
public MovieViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 
    View itemView = LayoutInflater. 
      from(viewGroup.getContext()). 
      inflate(R.layout.card_layout_movies, viewGroup, false); 
    Log.d(TAG, "create header view holder"); 
    return new MovieViewHolder(itemView); 
} 

@Override 
public void onBindViewHolder(MovieViewHolder movieViewHolder, int i) { 

    Log.d(TAG, "bind header view holder"); 
    MovieDetails mdet = movieList.get(i); 

    movieViewHolder.vTitle.setText(mdet.Title); 
    movieViewHolder.vPoster.setImageBitmap(mdet.imageViewPoster); 
    movieViewHolder.vFanart.setImageBitmap(mdet.imageViewFanart); 

    Log.d(TAG, "position: " + i + " holder: " + movieViewHolder + " text: " + movieViewHolder.vTitle); 


} 


public static class MovieViewHolder extends RecyclerView.ViewHolder { 

    protected TextView vTitle; 
    protected ImageView vPoster; 
    protected ImageView vFanart; 

    public MovieViewHolder(View v) 
    { 
     super(v); 
     vTitle = (TextView) v.findViewById(R.id.title); 
     vPoster = (ImageView) v.findViewById(R.id.imageViewPoster); 
     vFanart = (ImageView) v.findViewById(R.id.imageViewFanart); 

    } 

} 


public static class MovieDetails { 

    protected String title; 
    protected Bitmap imageViewPoster; 
    protected Bitmap imageViewFanart; 

    public MovieDetails(String title, Bitmap imageViewPoster,Bitmap imageViewFanart) 
    { 
     this.title = title; 
     this.imageViewPoster = imageViewPoster; 
     this.imageViewFanart = imageViewFanart; 
    } 
} 

public static MovieDetails generateDummyItem(String title, Bitmap poster, Bitmap fanart) { 

    MovieDetails mov = new MovieDetails(title, poster, fanart); 
    return mov; 
} 

public static List< MovieDetailsAdapter.MovieDetails> generateDummyData(int count, String title , Bitmap imageViewPoster, Bitmap imageviewFanart) { 


    ArrayList<MovieDetailsAdapter.MovieDetails> items = new ArrayList<MovieDetailsAdapter.MovieDetails>(); 

    for (int i=0; i < count; i++) { 

     items.add(new MovieDetailsAdapter.MovieDetails(title, imageViewPoster, imageviewFanart)); 
    } 

    return items; 
} 

}

現在,這裏是我的主類,活動類

public class MoviesListActivity extends AppCompatActivity { 

public MovieDetailsAdapter ca = new MovieDetailsAdapter(); 
public RecyclerView recList; 
private Button button; 



@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_movies_list); 
    RecyclerView recList = (RecyclerView) findViewById(R.id.cardList); 

    LinearLayoutManager llm = new LinearLayoutManager(this); 
    llm.setOrientation(LinearLayoutManager.VERTICAL); 
    recList.setLayoutManager(llm); 
    button = (Button) findViewById(R.id.button); 
    MyOnClickListener Listener = new MyOnClickListener(); 
    button.setOnClickListener(Listener); 

    recList.setItemAnimator(null); 

    Bitmap bittest1 = decodeSampledBitmapFromResource(getResources(), R.drawable.poster_example, 640, 955); 
    Bitmap bittest2 = decodeSampledBitmapFromResource(getResources(), R.drawable.fanart_example, 800, 450); 

    ca.setItemCount(5, "TestingTitle", bittest1, bittest2); 
    recList.setAdapter(ca); 
} 



public class MyOnClickListener implements View.OnClickListener { 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.button: 

       Bitmap bittest12 = decodeSampledBitmapFromResource(getResources(), R.drawable.poster2, 640, 955); 
       Bitmap bittest22 = decodeSampledBitmapFromResource(getResources(), R.drawable.fanart2, 800, 450); 

       Toast.makeText(getApplicationContext(), "msg msg", Toast.LENGTH_SHORT).show(); 

       ca.updateItem(1, "test", bittest12, bittest22); 
       // ca.addItem(1,"test",bittest12,bittest22); 
       break; 
      default: 
       break; 
     } 
    } 
} 

//------methods used for resizing the images down to smaller ones before loading into memory---// 


public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                 int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
    } 

而且最後,不是我可能很重要,我的CardView XML。

<android.support.v7.widget.CardView 
xmlns:card_view="http://schemas.android.com/apk/res-auto" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/card_view" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
card_view:cardCornerRadius="4dp" 
android:layout_margin="5dp"> 


<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <TextView 
     android:id="@+id/title" 
     android:layout_width="match_parent" 
     android:layout_height="20dp" 
     android:background="@color/bkg_card" 
     android:text="Movie Title" 
     android:gravity="center_vertical" 
     android:textColor="@android:color/white" 
     android:textSize="14dp"/> 

    <ImageView 
     android:elevation="5dp" 
     android:scaleType="fitCenter" 
     android:layout_width="100dp" 
     android:layout_height="150dp" 
     android:id="@+id/imageViewPoster" 
     android:text="Poster" 
     android:gravity="center_vertical" 
     android:layout_below="@id/title" 
     android:layout_marginTop="10dp" 
     android:layout_marginLeft="5dp"/> 

    <ImageView 
     android:id="@+id/imageViewFanart" 
     android:scaleType="fitCenter" 
     android:layout_alignBottom="@+id/imageViewPoster" 
     android:layout_toEndOf="@+id/imageViewPoster" 
     android:layout_width= "235dp" 
     android:layout_height="122dp" 
     android:layout_marginRight="5dp"/> 


</RelativeLayout> 

現在,有人在另一個討論表明我這是一個可能的原因:Why RecyclerView.notifyItemChanged() will create a new ViewHolder and use both the old ViewHolder and new one?

所以我加了onBind和適配器的onCreate方法裏面的日誌項目,看看是否能造成它,事實上,它不只是creatind一個額外的ViewHolders,但其中3個,每次我滾動新更新的卡,它似乎是重新綁定,onBind方法似乎每次調用。

根據線程中的解決方案將動畫設置爲'null'似乎對我的情況沒有任何影響,所以也許這不是造成它的原因。

任何想法?

回答

0

嗯,我解決了它。它似乎只在我通過XML方法加載圖像時纔會發生,如果我將它們加載到像畢加索這樣的第三方庫,延遲似乎消失了。喜歡的東西:

Picasso.with(context).load(MovieDetails.getPoster()) 
      .error(R.drawable.placeholder) 
      .placeholder(R.drawable.placeholder) 
      .into(movieViewHolder.imageViewPoster); 

的onBindViewHolder 內,而不是繞過位圖,只是通過對圖像的URL或位置的字符串。並將上下文傳遞給Adapter類。