Recyclerview Изменение элементов во время прокрутки

У меня есть RecyclerView. В каждой строке есть кнопка воспроизведения, текстовое изображение и Progressbar. при нажатии на кнопку воспроизведения необходимо воспроизвести аудио с моей SD-карты и выполнить прогресс. Пробковая панель. Проблема заключается в том, что я прокручиваю список изменений в Progress Progress в следующей строке. Я могу поместить 5 элементов на экране одновременно. Когда я перехожу к 6-му, 6-я строка поиска меняется внезапно.

public class ListAdapter extends RecyclerView.Adapter { private List stethitems; public Context mContext; public Activity activity; public Handler mHandler; static MediaPlayer mPlayer; static Timer mTimer; public ListAdapter(Activity activity,Context mContext,List stethitems) { this.stethitems = stethitems; this.mContext = mContext; this.activity = activity; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View rootView = LayoutInflater. from(mContext).inflate(R.layout.stethoscopeadapteritem, null, false); RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); rootView.setLayoutParams(lp); mHandler = new Handler(); return new MyViewHolder(rootView); } @Override public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) { final Historyitem dataItem = stethitems.get(position); final MyViewHolder myViewHolder = (MyViewHolder) viewHolder; myViewHolder.progressplay.setProgress(0); myViewHolder.stethdatetime.setText(dataItem.getReported_Time()); myViewHolder.stethhosname.setText(dataItem.getdiv()); if(dataItem.getPatient_Attribute().replaceAll(" ","").equals("")){ myViewHolder.stethdoctorname.setText(dataItem.getunit()); } else { myViewHolder.stethdoctorname.setText(dataItem.getPatient_Attribute()); } myViewHolder.stethstreamplay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FileDownload(dataItem.getmsg(), myViewHolder.progressplay); } }); } @Override public int getItemCount() { return stethitems.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { final CustomTextRegular stethdatetime; final CustomTextView stethhosname; final CustomTextBold stethdoctorname; final ImageButton stethstreamplay; final NumberProgressBar progressplay; public MyViewHolder(View itemView) { super(itemView); stethdatetime = (CustomTextRegular) itemView.findViewById(R.id.stethdatetime); stethhosname = (CustomTextView) itemView.findViewById(R.id.stethhosname); stethdoctorname = (CustomTextBold) itemView.findViewById(R.id.stethdoctorname); stethstreamplay = (ImageButton) itemView.findViewById(R.id.stethstreamplay); progressplay= (NumberProgressBar) itemView.findViewById(R.id.progressplay); } } public void FileDownload(final String downloadpath, final NumberProgressBar progressplay) { new AsyncTask() { NumberProgressBar progress; @Override protected void onPreExecute() { super.onPreExecute(); try { if(mPlayer!=null){ mPlayer.stop(); } }catch (Exception e){ } try { if(mTimer != null){ mTimer.purge(); mTimer.cancel(); } }catch (Exception e){ } } @Override protected NumberProgressBar doInBackground(NumberProgressBar... params) { int count; progress = progressplay; try { final List list = new ArrayList(); list.add(new BasicNameValuePair("pid",id)); URL url = new URL(Config.requestfiledownload + "?path=" + downloadpath); URLConnection connection = url.openConnection(); connection.connect(); int lenghtOfFile = connection.getContentLength(); // download the file InputStream input = new BufferedInputStream(url.openStream()); OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory() + "record.wav"); byte data[] = new byte[1024]; long total = 0; while ((count = input.read(data)) != -1) { total += count; // publishing the progress.... publishProgress((int) (total * 100 / lenghtOfFile)); output.write(data, 0, count); } output.flush(); output.close(); input.close(); } catch (Exception e) { } return progress; } @Override protected void onPostExecute(final NumberProgressBar numberProgressBar) { super.onPostExecute(numberProgressBar); try { StartMediaPlayer(numberProgressBar); } catch (Exception e){ e.printStackTrace(); } } }.execute(); } public void StartMediaPlayer(final NumberProgressBar progressbar){ Uri playuri = Uri.parse("file:///sdcard/record.wav"); mPlayer = new MediaPlayer(); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mPlayer.reset(); try { mPlayer.setDataSource(mContext, playuri); } catch (IllegalArgumentException e) { } catch (SecurityException e) { } catch (IllegalStateException e) { } catch (Exception e) { } try { mPlayer.prepare(); } catch (Exception e) { } mPlayer.start(); progressbar.setMax(mPlayer.getDuration()); mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if(mPlayer!=null) { mPlayer.release(); progressbar.setProgress(0); } if(mTimer != null){ mTimer.purge(); mTimer.cancel(); } } }); mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { progressbar.setProgress(mPlayer.getCurrentPosition()); } }); } },0,500); }} 

Попробуйте это

  1. Если вы используете ListView – переопределите следующие методы.

     @Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; } 
  2. Если вы используете RecycyclerView – переопределите метод getItemViewType() .

     @Override public int getItemViewType(int position) { return position; } 

Как следует из названия, представления в RecyclerView перерабатываются при прокрутке вниз. Это означает, что вам нужно сохранить состояние каждого элемента в своей модели Historyitem , что в этом случае будет Historyitem , и восстановить его в вашем onBindViewHolder .

1) Создайте позицию, максимум и любые другие переменные, необходимые для сохранения состояния ProgressBar в вашей модели.

2) Установите состояние вашего ProgressBar на основе данных в вашей модели подкачки; по щелчку, передайте позицию элемента в методы FileDownload / StartMediaPlayer .

 public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) { final Historyitem dataItem = stethitems.get(position); final MyViewHolder myViewHolder = (MyViewHolder) viewHolder; myViewHolder.progressplay.setMax(dataItem.getMax()); myViewHolder.progressplay.setProgress(dataItem.getPosition()); ... myViewHolder.stethstreamplay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FileDownload(dataItem.getmsg(), position); } }); 

3) Обновите индикатор выполнения, обновив модель поддержки и сообщив, что она была изменена.

 stethitems.get(position).setPosition(mPlayer.getCurrentPosition()); notifyItemChanged(position); 

Добавьте setHasStableIds(true); в конструкторе адаптера и переопределите эти два метода в адаптере.

 @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return position; } 

Поместите recylerView в представление NestedScroll View в свой XML и добавьте свойство nestedScrollingEnabled = false .

А на вашем адаптере onBindViewHolder добавьте эту строку

 final MyViewHolder viewHolder = (MyViewHolder)holder; 

Используйте этот объект viewHolder с вашими представлениями для setText или для любых событий щелчка.

например viewHolder.txtSubject.setText("Example");

У меня была та же проблема при обработке большого количества данных, она работает с 5, потому что она отображает пять элементов, которые видны на экране, но это дает проблему с большим количеством элементов. Дело в том ..

Иногда RecyclerView и listView просто пропускают Populating Data. В случае, если функция привязки RecyclerView пропускается во время прокрутки, но когда вы пытаетесь отладить адаптер recyclerView, он будет работать нормально, поскольку он будет вызывать onBind каждый раз, вы также можете увидеть официальное представление разработчика Google The World of listView . Примерно через 20 минут -30 минут они объяснят, что вы никогда не сможете предположить, что getView по позиции будет вызываться каждый раз.

поэтому, я предложу использовать

RecyclerView DataBinder, созданный satorufujiwara.

или

RecyclerView MultipleViewTypes Binder, созданный yqritc.

Это другие доступные Binders, если вы обнаружите, что их легко обойти.

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

Эта строка меняет ход на 0 при прокрутке

 myViewHolder.progressplay.setProgress(0); 

Сохраните его состояние где-нибудь, затем загрузите его в эту же строку.

Почему бы вам не попробовать так,

  HashMap progressHashMap = new HashMap<>(); //... if(!progressHashMap.containsKey(downloadpath)){ progressHashMap.put(downloadpath, mPlayer.getCurrentPosition()); } progressbar.setProgress(progressHashMap.get(downloadpath)); 

попробуй это

 @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { @Override public PointF computeScrollVectorForPosition(int targetPosition) { return LinearLayoutManager.this .computeScrollVectorForPosition(targetPosition); } }; linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); } 

см. также

Это ожидаемое поведение recyclerView. Поскольку представление переработано, ваши объекты могут попадать в случайные представления. Чтобы преодолеть это, вы должны указать, какой элемент будет помещен в какой-то вид. Эта информация может храниться в SparseBooleanArray. что вы можете сделать, это создать SparseBooleanArray в вашем адаптере, как это

 SparseBooleanArray selectedItems = new SparseBooleanArray(); 

всякий раз, когда изменяется ваш взгляд, выполните:

 selectedItems.put(viewItemIndex,true); 

Теперь в вашем onBindViewHolder

  if(selectedItems.get(position, false)){ //set progress bar of related to the view to desired position } else { //do the default } 

Это основной способ решить вашу проблему. Вы можете настроить эту логику на любую аналогичную проблему в recyclerView.

  • Эмулятор Android Studio не поставляется с Play Store для API 23
  • Нежелательная прокладка вокруг ImageView
  • Фрагмент Карт Google, возвращающий нуль внутри fragmentа
  • Android ExpandableListView - Поиск учебника
  • Добавление действия кнопки в пользовательское уведомление
  • Что более эффективно? Статические данные, передача данных, общие настройки, firebase database ...?
  • Android: Intent.ACTION_SEND с EXTRA_STREAM не прикрепляет изображения при выборе приложения Gmail на htc Hero
  • GoogleService не удалось инициализировать
  • Как показать Snackbar в верхней части экрана
  • «Требуется миграция области», исключение в android при извлечении значений из realm db
  • Android 4.1: Как проверить уведомления отключены для приложения?
  • Давайте будем гением компьютера.