The application uses recyclerwiew to display a list of contacts. In the old version of the application, 300mb photos of users rocked once and for all their lives and then they simply got to the OnBindViewHolder from the database. No problems in the display (in recyclerview) did not arise.
Now the photos are downloaded from the network as needed (if they were not previously recorded in the database), their display (asynchronously, of course) is recorded in the database and the result is displayed in the desired item. Everything looks great, but as soon as the list of contacts scroll, their photos are duplicated and only when the scroll stops, they disappear, they are re-created correctly. That is, recyclerview at the time of the stop flashes like a Christmas tree. It is clear that this is due to the fact that recyclerview reuses visible itemview. The problem is solved if you switch from recyclerview to listview and be sure to set it to setHasFixedSize (true). However, I just need to use recyclerview, not a listview.
Adapter code:
@Override public void onBindViewHolderCursor(ContactViewHolder holder, Cursor cursor) { String firstName = cursor.getString(cursor.getColumnIndex(DatabaseSchemas.Profile.FIRST_NAME)); String lastName = cursor.getString(cursor.getColumnIndex(DatabaseSchemas.Profile.LAST_NAME)); holder.mName.setText(String.format("%s %s", lastName, firstName)); long profileId = cursor.getInt(cursor.getColumnIndex(DatabaseSchemas.Profile.ID)); boolean gender = cursor.getString(cursor.getColumnIndex(DatabaseSchemas.Profile.SEX)).equals("M"); holder.mPhoto.setEmploeePhoto(mContext, profileId, gender, holder.mPhoto); //ВНИМАНИЕ ниже старый метод отображения изображений, который работает без проблем //ImageUtils.displayUserPhoto(mContext, profileId, gender, holder.mPhoto); holder.setHighlightQuery(mQuery); } Now in detail about the new method holder.mPhoto.setEmploeePhoto, which just either shows the image from the database, or downloads from the network, saves it to the database and shows it.
public void setEmploeePhoto(final Context context, final long mEmployee_id, final boolean gender, final ImageView imageView) { if (ImageUtils.userPhotoIsExist(context, mEmployee_id)){ ImageUtils.displayUserPhoto(context, mEmployee_id, gender, imageView); //ВНИМАНИЕ, это тот самый метод отображения фото, //который был закомментирован в OnBindViewHolder, //и ещё ниже он снова используется уже после окончания загрузки и записи в БД. //Но только пока он работал в OnBindViewHolder, фото прекрасно отображались при скроллинге, //а вот здесь появляется проблема с дублированием и перемигиванием новогодней ёлкой } else { JSONObject filter = new JSONObject(); JSONArray values = new JSONArray(); values.put(String.valueOf(mEmployee_id)); try { filter.put("values", values); filter.put("field", "user_id"); } catch (JSONException e) { e.printStackTrace(); return; } new SapApi(getContext()).getPhoto(filter) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<InputStream>() { @Override public void call(final InputStream inputStream) { //Если фото успешно скачалось из сети new LoadAndWritePhoto(context,mEmployee_id, gender, imageView, inputStream).execute(); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_LONG).show(); } }); } } public class LoadAndWritePhoto extends AsyncTask<Void, Void, Void> {//Потому что нельзя записывать данные в БД в главном потоке Context mmContext; long profileId; boolean gender; ImageView mImageView; InputStream inputStream; public LoadAndWritePhoto(Context mmContext, long profileId, boolean gender, ImageView mImageView, InputStream inputStream) { this.mmContext = mmContext; this.profileId = profileId; this.gender = gender; this.mImageView = mImageView; this.inputStream = inputStream; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) {//фоновая логика { try { PhotosSdCardWriter.writePhotosFromJson(mmContext, inputStream); } catch (Exception e){ e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(Void... values) {//обновление интерфейса до окончания выполнения потока (не требуется) super.onProgressUpdate(values); } @Override protected void onPostExecute(Void aVoid) {//результат фоновой логики super.onPostExecute(aVoid); try { ImageUtils.displayUserPhoto(mmContext, profileId, gender, mImageView); }catch (Exception e){ e.printStackTrace(); } } }
onBindViewHolder- miha_devImageViewimage before adding a new image to it -mImageView.setImageDrawable(null). - VadimonBindViewHoldermethod called on each view? One? - Vadim