以下是我用来显示包含电影图像和电影标题的电影项目的适配器代码。
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movie> movieList;
public MovieAdapter(List<Movie> movieList){
this.movieList = movieList;
}
@Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.movie_item,parent,false);
return new MovieViewHolder(view);
}
@Override
public void onBindViewHolder(final MovieViewHolder holder, int position) {
Movie movie = movieList.get(position);
holder.mv_name.setText(movie.getName());
class ImageDownloadTask extends AsyncTask<String,Void,Bitmap>{
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap = null;
URL url = createUrl(strings[0]);
Log.v("stringurl",strings[0]);
try {
bitmap = makeHttpRequest(url);
} catch (IOException e) {
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
holder.mv_img.setImageBitmap(bitmap);
}
private URL createUrl(String StringUrl){
URL url = null;
try {
url = new URL(StringUrl);
} catch (MalformedURLException e) {
return null;
}
return url;
}
private Bitmap makeHttpRequest(URL url) throws IOException{
HttpURLConnection urlConnection = null;
InputStream stream = null;
Bitmap bitmap = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(10000);
urlConnection.setReadTimeout(15000);
urlConnection.connect();
stream = urlConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(stream);
//Log.v("image:",bitmap.toString());
return bitmap;
}
catch (IOException e){
}
finally {
if (urlConnection != null) urlConnection.disconnect();
if (stream != null) stream.close();
}
return bitmap;
}
}
new ImageDownloadTask().execute(movie.getImg());
}
@Override
public int getItemCount() {
return movieList == null ? 0 : movieList.size();
}
class MovieViewHolder extends RecyclerView.ViewHolder{
ImageView mv_img;
TextView mv_name;
public MovieViewHolder(View itemView){
super(itemView);
mv_img = (ImageView) itemView.findViewById(R.id.mv_img);
mv_name = (TextView) itemView.findViewById(R.id.mv_name);
}
}
}
向下滚动图像时正在显示正在显示的其他电影的图像。例如,对于电影,将显示另一个电影图像,并且在第二个之后还显示另一个电影图像,并且在一系列不同的电影图像之后图像正确显示图像。
我从响应inBindViewHolder方法中获取的Url下载图像。 如何解决这个问题?
答案 0 :(得分:3)
<强>问题强>
这里要认识到ViewHolders是重用对象的池,当你滚动时,将出现一个重用的ViewHolder,并显示之前加载的图像。
通过使用Picasso或Glide或类似代码,您还可以使用缓存和效果等附加功能来保存大量代码。
<强>解决方案强>
首先,您可以使用像Picasso这样的库
compile 'com.squareup.picasso:picasso:2.5.2'
然后在您的recyclerview上的bind viewholder
Picasso.with(holder.imageView.getContext()).cancelRequest(holder.imageView);
Picasso.with(holder.imageView.getContext()).load("http://image.com/image.png").into(holder.imageView);
第一行代码将停止加载任何先前的图像。 第二行将加载当前图像。
将"http://image.com/image.png"
替换为您的图片网址。它需要字符串,URL等...
了解有关毕加索documentation
的更多信息答案 1 :(得分:1)
<强>问题强>
问题的根本原因是在视图被回收后检索到位图,因此在使用时会出现不匹配。
如何解决
答案 2 :(得分:1)
使用Picasso或Glide库在RecyclerView中显示图像
答案 3 :(得分:0)
我也一直在寻找这种解决方案,并且从Doron Yakovlev-Golani的答案中我为自己的解决方案,因为我的声誉很低,所以我无法添加评论。以下是我的解决方案,在这里当我在ImageView中添加图像时,我还向ImageView添加了ContentDescription作为参考,以供将来用于确定调用ViewHolder时需要显示的图像。 ContentDescription是作为字符串的ListView当前位置。 这是两个条件,第一个条件用于检查以前是否添加过的图像,如果以前没有添加过图像,则添加了图像。第二个图像已经添加到ImageView中,因此我通过调用ImageView ContentDescription来检查需要加载的图像,如果ContentDescription与当前位置匹配,则意味着我需要从列表中向ImageView添加当前位置图像。
在onViewHolder中,您可以这样使用:
//checking it is first time or not
if (holder.mv_img.getContentDescription() == null) {
//adding current position for loading current position image
imageView.setContentDescription(position + "");
}
if (holder.mv_img.getContentDescription().equals(position + "")) {
holder.mv_img.setImageBitmap(userLogoUri);
}