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

Элементы RecyclerView не меняются

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

Мои случаи:

  • при переключении между вкладками - измененные элементы
  • при выборе другого значения в счетчике на первой вкладке - элементы не изменены. (но данные изменяются в классе адаптера. Во-первых, он не является нулевым, а затем нулевым во время выбора. Но первые не нулевые данные не появляются, его замена нулевым значением. Найдена с использованием контрольных точек).

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

  • при выборе другого значения в счетчике на последней вкладке - измененных элементов.

Класс адаптера плеера для просмотра


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

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

}

фрагменты вкладки

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

Флаг установки 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;
    }
}

введите описание изображения здесь

Вопрос: Почему данные не изменяются при выборе опций в spinner иногда? (посмотрите мои случаи)

4b9b3361

Ответ 1

попробуйте использовать getChildFragmentManager() вместо getFragmentManager(), решит вашу проблему

Ответ 2

Я думаю, что вы должны реализовать onNothingSelected(), как показано ниже

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

Потому что onNothingSelected вызывается вместо onItemSelected при повторном выборе элемента счетчика.

Ответ 3

Проблема здесь в основном:

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

Это не гарантирует, что фрагмент, видимый пользователю, является последней границей. Вы устанавливаете viewPager.setOffscreenPageLimit(3);, что означает, что три фрагмента за время могут быть созданы, поэтому, когда вы находитесь на фрагменте, также создаются правый и левый.

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

Лично я бы изменил реализацию обработки spinner внутри фрагмента страницы, поскольку он действует только на фрагмент страницы.

Решение с помощью setUserVisibleHint

Привязать фрагмент страницы к основному, когда фрагмент становится видимым для пользователя. Обратите внимание на утечку памяти и освободите статическую ссылку

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

Решение с шиной

Еще одним быстрым решением может быть использование такой шины: http://square.github.io/otto/ Таким образом, каждый фрагмент подписывается на событие SelectedItemChanged и обновляет его. Основной фрагмент будет публиковать обновления каждый раз при изменении выбора счетчика.

Однако пример довольно большой, поэтому я не уверен, что нет других проблем. Попытайтесь поделиться полным проектом, чтобы получить более конкретную помощь.

Ответ 4

Когда вы работаете с recycleview, полагайтесь только на свои значения model class. Внесите все изменения в класс модели и создайте представления строк на основе полей этого класса модели.

i.e, вам нужно создать или изменить значения или просмотреть состояние на основе значений полей класса модели.

Например: если вы хотите сделать строку (позиция 30) невидимой, тогда я установлю флаг в классе модели с именем видимость и поставлю его в false.

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

Подобным образом вы можете создавать флаги, значения содержимого, сериализованные параметры из API и т.д. в классе модели. Этот метод сделает ваш reclycleview более понятным благодаря пользовательским взаимодействиям и изменениям API.

Ответ 5

Проверьте StudentViewPagerAdapter

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

почему вы называете newInstance снова?

Замените его следующим, return mFragmentList.get(position);

Ответ 6

Во-первых, убедитесь, что вы добавили эту строку после

setadapter :
adapter.notifyDataSetChanged();

Другой способ - сделать окончательный MyViewHolder держатель и позицию int

Пример.

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