2016-07-29 3 views
0

Я запрашиваю базу данных SQLite и помещаю данные в представление списка. Одна из строк базы данных содержит поле Url изображения (которое также может быть Uri).Изображения с url мерцания с помощью пользовательского адаптера курсора

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

Я уже понял, что такое поведение происходит, потому что представление списка повторно использует строки в прокрутке, но я понятия не имею, как исправить это поведение. Также я не могу использовать внешние библиотеки, такие как Picasso в этом проекте.

Вот мой адаптер код:

public class FilmsListCustomAdapter extends CursorAdapter { 

    private LayoutInflater cursorInflater; 

    public FilmsListCustomAdapter(Context context, Cursor c, int flags) { 
     super(context, c, flags); 
     cursorInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     TextView filmTitle = (TextView) view.findViewById(R.id.filmListTitle); 
     TextView filmScore = (TextView) view.findViewById(R.id.filmListScore); 
     ImageView filmImage = (ImageView)view.findViewById(R.id.filmListPoster); 
     ImageView filmSeen = (ImageView)view.findViewById(R.id.filmListSeen); 

     String title = cursor.getString(cursor.getColumnIndex("title")); 
     String score = cursor.getString(cursor.getColumnIndex("score")); 
     String url = cursor.getString(cursor.getColumnIndex("url")); 
     int seen = cursor.getInt(cursor.getColumnIndex("seen")); 

     if(Patterns.WEB_URL.matcher(url).matches()){ 
      LoadImage loadImage = new LoadImage(context,filmImage); 
      loadImage.execute(url); 
     } 
     else{ 
      Bitmap bmp = BitmapFactory.decodeFile(url); 
      CamImage camImage = new CamImage(context,Uri.parse(url)); 
      Bitmap rotetedIm = camImage.rotateCamImage(bmp,url); 
      if(rotetedIm!=null){filmImage.setImageBitmap(Bitmap.createScaledBitmap(rotetedIm, 850, rotetedIm.getHeight(), false));} 
      else{filmImage.setImageResource(R.drawable.no_poster);} 
     } 

     GlobalMethods methods = new GlobalMethods(context); 
     filmTitle.setTypeface(methods.getWalkFont()); 
     filmTitle.setText(title); 
     filmScore.setText(score); 
     if(seen==1){filmSeen.setImageResource(R.drawable.eye);} 
     else{filmSeen.setImageResource(0);} 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { 
     return cursorInflater.inflate(R.layout.film_row, viewGroup, false); 
    } 
} 
+0

Я не понимаю, почему вы не хотите использовать libassry Пикассо. Используйте библиотеку Picasso или Glide для отображения изображения, у которого есть функции для хранения изображения в catch, поэтому нет необходимости загружать внутреннее представление списка. Вот ссылка на Picasso: http://square.github.io/picasso/ и для Glide: https://github.com/bumptech/glide – Janak

+0

Это не то, чего я не хочу. Это школьный проект, и они требуют, чтобы я не использовал внешние библиотеки. –

ответ

1

Что, вероятно, происходит это:

  • Вы получаете веб-URL для изображения и очереди в AsyncTask, чтобы загрузить его для ImageView

  • Вы прокручиваете и ImageView перерабатывается

  • На этот раз ImageView получает локальный URL, так что вы делаете, что сразу

  • Ранее очередь AsyncTask дополняет и загружает в настоящее время несвязанного изображение над изображением вы просто положить в

Ключ чтобы очистить это, нужно обязательно отменить задачу, как только ImageView будет переработана. Один из способов сделать это - поставить ссылку на AsyncTask в тег в ImageView. Когда вы получаете переработанный ImageView, вы проверяете тег и проверяете, выполняется ли задание и отмените его, прежде чем запускать новую задачу.

Вы должны проверить эту статью на Android Developers Blog, это будет объяснить немного больше об этой проблеме и как это исправить:

Multithreading For Performance | Android Developers Blog

Я думаю, что эта статья была написана назад, когда AsyncTask s были изменен для работы в параллельных потоках, поскольку они говорят о выполнении задач, не соответствующих порядку. Они с тех пор вернулись к серийному исполнению, поэтому я не думаю, что эта часть применяется больше, но концепция похожа, так как ваша непосредственная загрузка локального изображения действует как задача, выполняющаяся не в порядке.

Две другие вещи, которые я бы рассмотреть следующие вопросы:

  • В getView, всегда называют imageView.setImageBitmap(null) первым, чтобы очистить любые остатки изображения в переработанной ImageView. Мне нравится инициализировать ImageView с очень нейтральным серым растровым изображением, представляющим состояние «Загрузка изображения».

  • Используйте файл AsyncTask для декодирования локальных файлов, а также для извлечения веб-файлов. Готов поспорить, что ваш список прокрутки будет казаться намного более плавным, когда вы это сделаете.

Смежные вопросы