Ниже приведен код адаптера, который я использую для отображения элементов фильма, которые содержат изображение фильма и название фильма.

   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);


   }
}
}

Во время прокрутки вниз изображения загружаются изображения других фильмов. Например, для фильма отображается другое изображение фильма, а через секунду также отображается другое изображение фильма и, таким образом, после серии различных изображений отображается правильное изображение. отображается

Я загружаю изображение с URL-адреса, полученного из ответа на метод onBindViewHolder. Как решить эту проблему?

2
Aravind Pulagam 23 Фев 2018 в 18:59

4 ответа

Лучший ответ

< Сильный > Проблема

Здесь важно понять, что ViewHolders - это пул повторно используемых объектов, и при прокрутке появится повторно используемый ViewHolder и будет показано ранее загруженное в него изображение.

Используя Picasso, Glide или аналогичные, вы экономите невероятное количество кода, используя дополнительные функции, такие как кэш и эффекты.

< Сильный > Решение

Сначала вы можете использовать библиотеку, как Пикассо

compile 'com.squareup.picasso:picasso:2.5.2'

Тогда в вашемайзере вид на 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 изображения. Требуется строка, URL и т. Д.

Подробнее о Пикассо читайте здесь.

4
toshkinl 23 Фев 2018 в 16:15

< Сильный > Проблема

Основной причиной вашей проблемы является то, что растровое изображение извлекается после того, как представление было переработано, и, таким образом, вы получаете несоответствие при его использовании.

Как решить

  • Краткий ответ - использовать библиотеку кэширования изображений, например Picasso или Glide. Эти библиотеки предназначены для того, чтобы делать именно то, что вы пытаетесь достичь.
  • Другой вариант - попытаться сделать это самостоятельно. Что вы можете сделать, это сохранить URL-адрес внутри держателя и вызывать setImageBitmap() только в том случае, если текущий URL совпадает с только что выбранным. Чтобы сохранить URL-адрес, просто добавьте поле URL-адреса в MovieViewHolder и сохраняйте URL-адрес всякий раз, когда вы извлекаете изображение и проверяете его на соответствие по завершении загрузки.
1
Doron Yakovlev-Golani 23 Фев 2018 в 19:32

Я также искал это решение, и из ответа Дорон Яковлев-Голани я сам нашел решение, так как у меня низкая репутация, поэтому я не могу добавить комментарий. Ниже мое решение, здесь, когда я добавил изображение в ImageView, я также добавил ContentDescription в ImageView в качестве ссылки для будущего использования, чтобы определить, какое изображение нужно показать при вызове ViewHolder. ContentDescription - это текущая позиция ListView в виде String. Вот два условия, первое для проверки ранее добавленного изображения или нет, если изображение не добавлено ранее, я добавил изображение. второе изображение уже добавлено в 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);
    }
0
Rhidoy 6 Сен 2018 в 14:21

Используйте Picasso или Glide Библиотека для отображения изображений в RecyclerView

1
Ramesh R 23 Июл 2019 в 13:03