studio recyclerview hacer como android android-viewpager android-recyclerview adapter

android - hacer - recyclerview adapter notifydatasetchanged



Los artículos de RecyclerView no están cambiando (6)

Tengo un RecyclerView en un fragmento que se repite en TabLayout. Estoy teniendo el problema de la vista sin cambios en RecyclerView. Tengo una ruleta en cada pestaña. Quiero cambiar los datos cuando se seleccionan los elementos de giro.

Mis casos:

  1. cuando se cambia entre pestañas - artículos cambiados
  2. al seleccionar otro valor en el control de giro en la primera pestaña, los elementos no se han modificado . (pero los datos están cambiando en la clase de adaptador. Es decir. Primero, no es nulo, sino que es nulo durante la selección. Pero los primeros datos no anulados no aparecen, se reemplazan con nulos. Se encontraron utilizando puntos de interrupción).

    Nota: En este caso, cuando se cambia la pestaña, los elementos se cambian a los elementos seleccionados de la ruleta en la pestaña anterior. Y luego desaparece y muestra los elementos actuales en la pestaña.

  3. al seleccionar otro valor en el control de giro en la última pestaña: elementos modificados .

Mi clase de adaptador de buscapersonas

public class StudentViewPagerAdapter extends FragmentStatePagerAdapter { private final List<StudentList> mFragmentList = new ArrayList<>(); private final List<Clazz> mFragmentTitleList = new ArrayList<>(); public StudentViewPagerAdapter(FragmentManager fm) { super(fm); } public void addFragment(StudentList fragment,Clazz clazz){ mFragmentList.add(fragment); mFragmentTitleList.add(clazz); } @Override public Fragment getItem(int position) { return StudentList.newInstance(mFragmentTitleList.get(position)); } @Override public int getCount() { return mFragmentList.size(); } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position).getName(); } }

mi clase de adaptador RecyclerView

public class PeopleAdapter extends RecyclerView.Adapter<PeopleAdapter.MyViewHolder> implements View.OnClickListener { private List<Student> dataList; private Context context; private Clicker clicker; public PeopleAdapter(List<Student> data, Context context, Clicker clicker) { this.dataList = data; this.context = context; this.clicker = clicker; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.people_list_item, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { Student data=dataList.get(position); holder.email.setText(data.getEmail()); holder.name.setText(data.getName()); holder.phone.setText(data.getPhone()); Glide.with(context).load(Method.getImageUrl(MyConfiguration.STUDENT_IMAGE_URL, data.getStudentId())).asBitmap().into(holder.profilePic); holder.edit.setOnClickListener(this); holder.edit.setTag(position); } @Override public int getItemCount() { return dataList.size(); } @Override public void onClick(View v) { clicker.OnItemClicked((int) v.getTag(),null); } static class MyViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.name) TextView name; @BindView(R.id.email) TextView email; @BindView(R.id.phone) TextView phone; @BindView(R.id.image) ImageView profilePic; @BindView(R.id.imageedit) ImageView edit; MyViewHolder(View view) { super(view); ButterKnife.bind(this,view); } } }

fragmentos de pestañas

public class StudentList extends Fragment implements SectionChanger { @BindView(R.id.studentlist) RecyclerView mRecyclerview; CompositeDisposable disposable; private Unbinder unbinder; private Clazz clazz; private Requester requester; public StudentList() { StudentInformation.bindSectionChangeListener(this); } public static StudentList newInstance(Clazz clazz) { StudentList fragment=new StudentList(); Bundle args = new Bundle(); args.putSerializable(MyConfiguration.SECTIONS, clazz); fragment.setArguments(args); return fragment; } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); disposable.clear(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_student_list, container, false); unbinder = ButterKnife.bind(this, view); LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerview.setLayoutManager(mLayoutManager); initializeRetrofit(); if (getArguments() != null) { clazz = (Clazz) getArguments().getSerializable(MyConfiguration.SECTIONS); loadStudentJson(clazz != null ? clazz.getClassId() : null, clazz != null ? clazz.getSections().get(0).getSectionId() : null); } return view; } /** * Load students list */ public void loadStudentJson(String class_id,String section_id) { disposable = new CompositeDisposable(requester.getStudentsInSection(class_id,section_id) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe( this::handleResponse, this::handleError ) ); } private void handleResponse(List<Student> list) { PeopleAdapter adapter=new PeopleAdapter(list, getActivity(), (position, name) -> Toast.makeText(getActivity(), position, Toast.LENGTH_LONG).show()); mRecyclerview.setAdapter(adapter); adapter.notifyDataSetChanged(); } private void handleError(Throwable error) { Toast.makeText(getActivity(), "Error " + error.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); } @Override public void ChangeData(Section section) { loadStudentJson(section.getClassId(),section.getSectionId()); } public void initializeRetrofit(){ HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); CookieHandler handler=new Cookies(getActivity()); //ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(getActivity())); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(interceptor) .cookieJar(new JavaNetCookieJar(handler)) .build(); requester = new Retrofit.Builder() .baseUrl(MyConfiguration.BASE_URL) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(JacksonConverterFactory.create()) .client(client) .build().create(Requester.class); } }

Fragmento de configuración de ViewPager

public class StudentInformation extends Fragment implements TabLayout.OnTabSelectedListener, AdapterView.OnItemSelectedListener { // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private Unbinder unbinder; // TODO: Rename and change types of parameters private String mParam1; private String mParam2; CompositeDisposable disposable; List<Section> sectionsList=new ArrayList<>(); private OnConnectingFragments mListener; @BindView(R.id.tabs) TabLayout mTabLayout; @BindView(R.id.viewpager) ViewPager viewPager; @BindView(R.id.secSelector) Spinner spinner; @BindView(R.id.className) TextView className; private static SectionChanger sectionChanger; public StudentInformation() { // Required empty public constructor } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param param1 Parameter 1. * @param param2 Parameter 2. * @return A new instance of fragment StudentInformation. */ // TODO: Rename and change types and number of parameters public static StudentInformation newInstance(String param1, String param2) { StudentInformation fragment = new StudentInformation(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); disposable.clear(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view=inflater.inflate(R.layout.fragment_student_information, container, false); unbinder = ButterKnife.bind(this, view); LoadDataAndSetupViewPager(); //setupViewPager(viewPager); mTabLayout.setupWithViewPager(viewPager); mTabLayout.addOnTabSelectedListener(this); spinner.setOnItemSelectedListener(this); // ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, MyConfiguration.CLASS_SECTIONS); // spinner.setAdapter(arrayAdapter); return view; } // TODO: Rename method, update argument and hook method into UI event public void onButtonPressed(Fragment fragment,String tag) { if (mListener != null) { mListener.onClickedMenu(fragment,tag); } } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnConnectingFragments) { mListener = (OnConnectingFragments) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ /*private void setupViewPager(ViewPager viewPager) { StudentViewPagerAdapter adapter = new StudentViewPagerAdapter(getFragmentManager()); //adapter.addFragment(new StudentList(),"exam"); for (String claz: MyConfiguration.CLASS) adapter.addFragment(new StudentList(), claz); viewPager.setAdapter(adapter); }*/ @OnClick(R.id.add) public void OnClicked(LinearLayout view){ onButtonPressed(new AddStudent(),"addStudent"); } @Override public void onTabSelected(TabLayout.Tab tab) { className.setText(String.format(getString(R.string.class_name), tab.getPosition()+1)); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } public void LoadDataAndSetupViewPager() { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(getActivity())); OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); Requester requester=new Retrofit.Builder() .baseUrl(MyConfiguration.BASE_URL) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(JacksonConverterFactory.create()) .client(client) .build().create(Requester.class); disposable=new CompositeDisposable(requester.getClasses() ////GETTING CLASSES//// .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .flatMapIterable(clazzs -> clazzs) .flatMap(clazz -> requester.getDivision(clazz.getClassId()) ////GETTING SECTIONS//// .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .flatMapIterable(sections -> sections) .doOnNext(section -> {sectionsList.add(section); Log.v("section_id",section.getSectionId());}) .takeLast(1) .map(section -> clazz) ) .doOnNext(clazz -> {clazz.setSections(sectionsList); Log.v("List Size",sectionsList.size()+""); sectionsList=new ArrayList<>(); }) .toList() .subscribe(this::SetupViewPager, throwable -> Log.e("retroerror",throwable.toString()))); } public void SetupViewPager(List<Clazz> classList){ StudentViewPagerAdapter adapter = new StudentViewPagerAdapter(getFragmentManager()); //adapter.addFragment(new StudentList(),"exam"); for (Clazz claz: classList){ adapter.addFragment(new StudentList(), claz); } viewPager.setAdapter(adapter); viewPager.setOffscreenPageLimit(3); viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); List<Section>sections=classList.get(position).getSections(); ArrayAdapter<Section> arrayAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, sections); spinner.setAdapter(arrayAdapter); } }); } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Section section= (Section) parent.getItemAtPosition(position); sectionChanger.ChangeData(section); } @Override public void onNothingSelected(AdapterView<?> parent) { } public static void bindSectionChangeListener(SectionChanger changer){ sectionChanger=changer; } }

La pregunta es: ¿por qué los datos no se modifican cuando se seleccionan opciones en la ruleta a veces? (mira mis casos)


Creo que deberías implementar onNothingSelected () como se muestra a continuación

Section mCurrentSection; @Override public void onNothingSelected(AdapterView<?> parent) { int position = parent.getSelectedItemPosition(); Section section= (Section) parent.getItemAtPosition(position); if (mCurrentSection == null || !mCurrentSection.equals(section)) { mCurrentSection = section; sectionChanger.ChangeData(section); } }

Porque se llama a onNothingSelected en lugar de a onItemSelected cuando vuelve a seleccionar un elemento del selector.


Cuando trabaje con recycleview, confíe solo en los valores archivados de su clase modelo . Realice todos los cambios a la clase de modelo y cree vistas de fila basadas en los campos de esta clase de modelo.

es decir, tiene que crear o cambiar valores o ver el estado en función del valor de los campos de la clase modelo.

Por ejemplo: si desea que una fila (posición 30) sea invisible, estableceré una marca en la clase del modelo llamada visibilidad y la estableceré en falsa .

en este caso, siempre que la vista se vuelva a dibujar en la interfaz de usuario, tendremos que verificar el indicador y establecer la visibilidad según el valor del campo de esa clase de modelo.

De este modo, puede crear marcas, valores de contenido, parámetros serializados de API, etc. en la clase modelo. Este método hará que su consulta sea más consistente a través de las interacciones del usuario y los cambios en la API.


El problema es principalmente aquí:

public StudentList() { StudentInformation.bindSectionChangeListener(this); }

Esto no asegura que el fragmento visible para el usuario sea el último límite. Establece viewPager.setOffscreenPageLimit(3); lo que significa que se pueden crear instancias de tres fragmentos por tiempo, por lo que cuando se encuentra en un fragmento, también se crean el derecho y el izquierdo.

Esto explica por qué el último funciona bien, porque no hay un fragmento correcto, y probablemente sea el último en ser instanciado y enlazado.

Personalmente, cambiaría la implementación que maneja el control de giro dentro del fragmento de página, ya que actúa solo en el fragmento de página.

Solución con un setUserVisibleHint

Vincule el fragmento de la página al principal cuando el fragmento sea visible para el usuario. Presta atención a la pérdida de memoria y libera la referencia estática.

@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(isVisibleToUser){ StudentInformation.bindSectionChangeListener(this); } }

Solución con un bus

Otra solución rápida podría ser utilizar un bus como este: http://square.github.io/otto/ De esta manera, cada fragmento se suscribirá a un evento SelectedItemChanged y se actualizará. El fragmento principal publicará las actualizaciones cada vez que se cambie la selección de la rueda giratoria.

Sin embargo, el ejemplo es bastante grande, así que no estoy muy seguro de que no haya otros problemas. Intenta compartir un proyecto completo para recibir ayuda más específica.


En primer lugar, compruebe que agregue esta línea después de

setadapter : adapter.notifyDataSetChanged();

Otra forma es hacer final el titular MyViewHolder y la posición int

ejemplo.

public void onBindViewHolder(final MyViewHolder holder, final int position) {


Revise su StudentViewPagerAdapter

@Override public Fragment getItem(int position) { return mFragmentList.get(position).newInstance(mFragmentTitleList.get(position)); }

¿Por qué vuelves a llamar a newInstance ?

Reemplácelo con lo siguiente, return mFragmentList.get(position);


intente usar getChildFragmentManager () en lugar de getFragmentManager () resolverá su problema