0
我在我的項目中使用Recycler View。我生成pinterestlike多列網格。一切正常。我的應用程序從外部存儲裝載數據(也是圖像)。當在UI線程中加載時,滾動性能非常差。所以我決定創建AsyncTask來加載來自路徑的圖像,而這正在向下滾動的同時搖動。當我再次滾動時,我遇到了問題,因爲重新創建單元格與網格佈局有關。它正在重新整理,對用戶來說可能很差。在內存中緩存圖像(其中很多)不好想法,我認爲,也許這是一個選項來存儲有關每個單元格ImageView大小的信息,並保持它的重用?Android將緩存的圖像加載到RecyclerView中重新排列網格
我RecyclerView佈局適配器看起來是這樣的:
public class MainGridAdapter extends RecyclerView.Adapter<ArticleViewHolder> {
private List<Article> articleList;
private Context context;
public MainGridAdapter(Context context, List<Article> articleList) {
this.articleList = articleList;
this.context = context;
}
@Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.article_cell, null);
ArticleViewHolder avc = new ArticleViewHolder(layoutView);
return avc;
}
@Override
public void onBindViewHolder(ArticleViewHolder holder, final int position) {
Typeface StagMedium = Typeface.createFromAsset(context.getAssets(), "fonts/Stag-Medium.otf");
holder.articleTitle.setText(articleList.get(position).getTitle());
holder.articleTitle.setTypeface(StagMedium);
//Wczytuję obrazek
Log.v("DDD", articleList.get(position).getTitle());
Log.v("DDD", String.valueOf(articleList.get(position).getId()));
//TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, articleList.get(position).getCover_height());
//holder.container.setLayoutParams(params);
BitmapWorkerTask task = new BitmapWorkerTask(holder.articleImage);
task.execute(articleList.get(position).getCover_local_path());
/*
File file = new File(articleList.get(position).getCover_local_path());
if(file.exists()) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), bmOptions);
holder.articleImage.setImageBitmap(bitmap);
}
*/
//Jeżeli materiał to video to pokazuję ikonkę
Log.v("DDD", "Type: " + articleList.get(position).getType());
if(articleList.get(position).getType().equals("article")) {
Log.v("DDD", "Article");
holder.articleVideoIcon.setImageResource(android.R.color.transparent);
} else {
Log.v("DDD", "Video");
holder.articleVideoIcon.setImageResource(R.drawable.play);
}
holder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v("DDD", "Klikłem sobie na pozycję: " + String.valueOf(position));
Intent intent= new Intent(context,SingleArticle.class);
Log.v("DDD", String.valueOf(articleList.get(position).getId()));
intent.putExtra("articleId", articleList.get(position).getId());
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return articleList.size();
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String path = "";
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(String... params) {
path = params[0];
File file = new File(path);
if (file.exists()) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(),bmOptions);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//Bitmap resized_bitmap = Bitmap.createScaledBitmap(bitmap, Math.round(width/2), Math.round(height/2), false);
//return resized_bitmap;
return bitmap;
} else {
return null;
}
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
}
您可以更好地使用圖像緩存庫,如畢加索,Glide。我認爲這裏的問題是使用Recyclerview,因爲它每次滾動時都會加載數據。您現在編寫的代碼會每次加載數據。但是,如果使用圖像緩存庫,它將加載緩存的圖像,而不是從路徑(本地或遠程)再次加載它。緩存圖像是最好的情況..希望它有幫助。 – HourGlass
我已經想過了,但是當我將使用畢加索異步時,它不一樣嗎?從緩存中加載也需要一些時間,所以快速滾動時不會立即處理它。另一方面,在UI線程中使用picasso會在滾動時降低性能。或者我錯了?我必須從本地路徑加載圖像,因爲客戶端需要應用程序加載離線(在初始化在線和下載數據後)。 – skrystos
當你使用畢加索時,不是確切的情況,畢加索會立即停止緩存圖像,當recyclerview子項失去它的知名度(當滾動)..再加上你也可以指定畢加索有關圖像緩存大小應該是..所以我認爲你應該嘗試這..這將避免你的異步任務以及..當圖像加載時,你可以使用持有人顯示默認圖像/ drawable用戶.. – HourGlass