Подтвердить что ты не робот

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

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

public class ListAdapter extends RecyclerView.Adapter {

    private List<Historyitem> stethitems;
    public Context mContext;
    public Activity activity;
    public Handler mHandler;

    static MediaPlayer mPlayer;
    static Timer mTimer;

    public ListAdapter(Activity activity,Context mContext,List<Historyitem> 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, Integer, NumberProgressBar>() {
            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<NameValuePair> list = new ArrayList<NameValuePair>();
                    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);
    }}
4b9b3361

Ответ 1

Пожалуйста, попробуйте

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

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

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

Ответ 2

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

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

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

Ответ 3

Как следует из названия, представления в RecyclerView перерабатываются при прокрутке вниз. Это означает, что вам нужно сохранить состояние каждого элемента в вашей модели подкачки, что в данном случае будет 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);

Ответ 4

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

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

final MyViewHolder viewHolder = (MyViewHolder)holder;

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

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

Ответ 5

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

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

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

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

или

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

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

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

Ответ 6

Эта строка меняет прогресс до 0 на каждой привязке

myViewHolder.progressplay.setProgress(0);

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

Ответ 7

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

    HashMap<String, Integer> progressHashMap = new HashMap<>();

    //...
    if(!progressHashMap.containsKey(downloadpath)){
        progressHashMap.put(downloadpath, mPlayer.getCurrentPosition());
    }

    progressbar.setProgress(progressHashMap.get(downloadpath));

Ответ 8

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

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

см. это также

Ответ 9

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

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

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

Я надеюсь, что это будет возможным решением. Спасибо

Ответ 10

Это ожидаемое поведение 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.

Ответ 11

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

Так что все, что вам нужно сделать, это в обязательное время сказать, чтобы оно не обновлялось.

Вот так должен выглядеть ваш onBindViewHolder

@Override
@SuppressWarnings("unchecked")
public void onBindViewHolder(final BaseViewHolder holder, final int position) {
    holder.bind(mList.get(position));

    // This is the mighty fix of the issue i was having
    // where recycler view was updating the items on scroll.
    holder.setIsRecyclable(false);
}