Items being repeated in a RecyclerView

2

I have a fragment v4 that is managed by a SectionsPagerAdapter . In fragment I have a RecyclerView that has a Adapter custom that receives a ArrayList that contains exactly 96 objects, which represents the hours of the day, ex: position 0 = 00:00, 1 = 00:15, 2 = 00:30, 3 = 00:45, 4 = 01:00, and so on until 96 = 23:45. In addition to the time itself, it also has a nome field and a procedimentos field. These fields will only be filled if someone is scheduled for the time, otherwise they are "" .

The problem is that it is shuffling everything when it comes to assembling the adapter! One time it repeats in several random places that have not yet been scheduled ... by what I noticed in log , as does scroll in recyclerView , it automatically updates adapter ... I think that's what this bug ... but I do not know how to solve ...

Note that in the image below, it should have appeared only at position 01:45, but it also appears at 00:30, detail that at this position of ArrayList the name field is empty.

Iam2daystryingtofindtheproblembutIcouldnot...itmustbesomethingsillythatIamnotrealizing=(

followthecodes:

Fragment

publicclassFragmentAgendaextendsFragment{privatestaticMVP.Presenterpresenter;privateViewrootView;privateAdapterHorariosadapterHorarios;publicstaticFragmentAgendanewInstance(intsectionNumber,StringdataInicial){FragmentAgendafragment=newFragmentAgenda();Bundleargs=newBundle();args.putInt(ARG_SECTION_NUMBER,sectionNumber);args.putString(ARG_DATA_CONSULTA,dataInicial);fragment.setArguments(args);returnfragment;}@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){this.rootView=inflater.inflate(R.layout.fragment_agenda,container,false);this.dad=(AgendaActivity)getContext();if(presenter==null)presenter=newPresenter();presenter.setView(this,getContext());presenter.retrieveAgendaDia(getArguments(),savedInstanceState);returnrootView;}@OverridepublicvoidonStart(){super.onStart();initViews();}@OverridepublicvoidonSaveInstanceState(BundleoutState){super.onSaveInstanceState(outState);getArguments().putParcelableArrayList(KEY_CONSULTAS,presenter.getConsultas());getArguments().putParcelableArrayList(KEY_HORARIOS,presenter.getHorarios());}privatevoidinitViews(){RecyclerViewrecyclerView=(RecyclerView)rootView.findViewById(R.id.containerHorario);recyclerView.setHasFixedSize(true);recyclerView.setLayoutManager(newLinearLayoutManager(getContext()));adapterHorarios=newAdapterHorarios(getActivity(),presenter.getHorarios(),presenter);recyclerView.setAdapter(adapterHorarios);}@OverridepublicvoidupRecyclerView(){adapterHorarios.notifyDataSetChanged();}}

Presenter

publicclassPresenterextendsPresenterDadimplementsMVP.Presenter{privateMVP.Modelmodel;privateMVP.Viewview;privateContextcontexto;privateArrayList<Consulta>consultas;privateArrayList<Consulta>horarios;privateStringmesAno;publicPresenter(){this.model=newModel(this);this.consultas=newArrayList<>();this.horarios=newArrayList<>();}@OverridepublicContextgetContext(){returncontexto;}@OverridepublicvoidsetView(MVP.Viewview,Contextcontext){this.view=view;this.contexto=context;}@OverridepublicvoidretrieveAgendaDia(Bundleargs,BundlesavedInstanceState){Stringdia=String.valueOf(args.getInt(MVP.View.ARG_SECTION_NUMBER));mesAno=args.getString(MVP.View.ARG_DATA_CONSULTA);if(args.getParcelableArrayList(MVP.View.KEY_CONSULTAS)!=null){horarios=args.getParcelableArrayList(MVP.View.KEY_HORARIOS);consultas=args.getParcelableArrayList(MVP.View.KEY_CONSULTAS);Stringdata=String.format(dia,mesAno);model.montarHorarios(horarios,consultas,data);return;}model.retrieveAgendaDia(consultas,dia,mesAno);}@OverridepublicArrayList<Consulta>getHorarios(){returnhorarios;}@OverridepublicArrayList<Consulta>getConsultas(){returnconsultas;}@OverridepublicvoidupRecyclerView(){view.upRecyclerView();}}

Model

publicclassModelimplementsMVP.Model{privatefinalMVP.Presenterpresenter;privatefinalConsultaCtrlconsultaCtrl;publicModel(Presenterpresenter){this.presenter=presenter;this.consultaCtrl=newConsultaDAO();}@OverridepublicvoidretrieveAgendaDia(finalArrayList<Consulta>consultas,finalStringdia,finalStringmesAno){consultaCtrl.retriveList(consultas,dia,mesAno,newCallback(){@Overridepublicvoidresult(booleanb){if(b){Stringdata=String.format(Locale.GERMAN,"%02d/%s", Integer.valueOf(dia), mesAno);
                montarHorarios(presenter.getHorarios(), consultas, data);
            }
        }
    });
}

@Override
public void montarHorarios(ArrayList<Consulta> horarios, ArrayList<Consulta> consultas, String dataConsulta) {
    if (horarios.size() < 96) {
        horarios.clear();
        int hora = 0, flagHora = 0;
        int minuto = -15;

        for (int id = 0; id <= 95; id++) {
            if ((flagHora - 4) == 0) {
                hora++;
                flagHora = 1;
            } else flagHora++;

            if (minuto >= 45) minuto = 0;
            else minuto += 15;

            String data = String.format("%s %s:%s",
                    dataConsulta,
                    String.format(Locale.GERMAN, "%02d", hora),
                    String.format(Locale.GERMAN, "%02d", minuto)
            );
            horarios.add(new Consulta(hora, minuto, data.replace("-", "/")));
        }

        for (Consulta c : consultas) {
            for (int i = 0; i < horarios.size(); i++) {
                if (horarios.get(i).getDataConsulta().equals(c.getDataConsulta())) {
                    horarios.set(i, c);
                    i = horarios.size();
                }
            }
        }
    }

    presenter.upRecyclerView();
}
}

Adapter

public class AdapterHorarios extends RecyclerView.Adapter<HorariosViewHolder> {
private ArrayList<Consulta> consultas;
private Context contexto;

public AdapterHorarios(Context contexto, ArrayList<Consulta> consultas, MVP.Presenter presenter) {
    this.consultas = consultas;
    this.presenter = presenter;
    this.contexto = contexto;
}

@Override
public HorariosViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater
            .from(parent.getContext())
            .inflate(R.layout.adapter_agenda, parent, false);
    return new HorariosViewHolder( view );
}

@Override
public void onBindViewHolder(HorariosViewHolder holder, final int position) {
    holder.setDados(consultas.get(position));
}

@Override
public int getItemCount() {
    return consultas.size();
}
}

Holder

public class HorariosViewHolder extends RecyclerView.ViewHolder {
private TextView hora, nomePaciente, procedimentos;
private ImageView staus;

public HorariosViewHolder(View itemView) {
    super(itemView);

    staus = (ImageView) itemView.findViewById(R.id.check);
    nomePaciente = (TextView) itemView.findViewById(R.id.nomePaciente);
    procedimentos = (TextView) itemView.findViewById(R.id.procedimentos);
    hora = (TextView) itemView.findViewById(R.id.hora);
}

public void setDados(Consulta consulta){
    if (consulta.getNomePaciente() != null){
        staus.setImageResource(R.drawable.ic_radio_button_checked);
        nomePaciente.setText(consulta.getNomePaciente());
        procedimentos.setText(consulta.getDataConsulta());
    }
    hora.setText(Datas.formatHoraConsulta(consulta.getHoraConsulta(), consulta.getMinutoConsulta())); // retorna hora ex: "07:15"
}
}
    
asked by anonymous 05.04.2017 / 02:21

1 answer

3

The RecyclerView.Adapter implements the "View Holder" pattern by using the RecyclerView.ViewHolder class using it in the onCreateViewHolder() and onBindViewHolder() methods, allowing a previously created view to be reused.

It is your responsibility, in the onBindViewHolder() method, to return this filled view with the values corresponding to the RecyclerView item in question.

The method that is being used for this purpose is setDados() of SchedulesViewHolder. However, it only refreshes the view when consulta.getNomePaciente() != null . When this is not the case, the view is returned unchanged (only hora is updated), it has values from an item previously used.

You should change the method so that both situations are handled.

public void setDados(Consulta consulta){
    if (consulta.getNomePaciente() != null){
        staus.setImageResource(R.drawable.ic_radio_button_checked);
        nomePaciente.setText(consulta.getNomePaciente());
        procedimentos.setText(consulta.getDataConsulta());
    }else{
        staus.setImageResource(R.drawable.ic_radio_button_checked);//ou outra, não sei
        nomePaciente.setText("");
        procedimentos.setText("");
    }
    hora.setText(Datas.formatHoraConsulta(consulta.getHoraConsulta(), consulta.getMinutoConsulta())); // retorna hora ex: "07:15"
}
    
05.04.2017 / 16:18