【问题标题】:RecyclerView Items are not changingRecyclerView 项目没有改变
【发布时间】:2017-03-21 07:46:02
【问题描述】:

我在 TabLayout 中重复的片段中有一个 RecyclerView。我在 RecyclerView 中遇到了视图未更改的问题。我在每个选项卡上都有一个微调器。我想在选择微调器项目时更改数据。

我的案例:

  1. 在标签之间切换时 - 项目已更改
  2. 在第一个选项卡的微调器中选择另一个值时 -未更改的项目。 (但是适配器类中的数据正在发生变化。即,首先,在选择过程中它不为空,然后为空。但第一个不为空的数据没有出现,它被替换为空。使用断点找到它)。

    注意:在这种情况下,切换选项卡时,项目会更改为 微调器在上一个选项卡中选择了项目。然后它消失了 并在标签中显示当前项目。

  3. 在最后一个选项卡的微调器中选择另一个值时 -项目已更改

我的视图寻呼机适配器类


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

我的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;
    }
}

问题是:为什么有时在微调器中选择选项时数据会保持不变?(看看我的案例)

【问题讨论】:

  • 即使我像你一样做一些相同的设置,我也面临同样的问题。问题是 viewpager 正在返回我片段的不同实例。因此,如果您获得正确的片段实例,请检查一次。我使用下面的方法来获取正确的片段,除了没有方法给我正确的实例 - ((MyClass) viewPager.getAdapter().instantiateItem(viewPager, 0)).refreshData();
  • 那么,在handleResponse() 中您正确地将数据设置为PeopleAdapter,但数据没有显示?
  • 是的。但是当我切换到下一个选项卡时,会出现之前选择的数据,然后突然替换为当前选项卡中的新数据。此外,最后一个选项卡没有问题。它显示了数据的及时变化。 @azizbekian
  • 我猜如果你在第一页并从微调器中选择一些东西,它会正常工作。只要您切换选项卡并返回到第一个选项卡,然后切换微调器,数据就不会被更改,对吧?
  • @azizbekian 不,在第一页它不起作用

标签: android android-viewpager android-recyclerview adapter


【解决方案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); 意味着每次可以实例化三个片段,因此当您在片段上时,也会创建右侧和左侧的片段。

      这解释了为什么最后一个效果很好,因为没有正确的片段,并且可能是最后一个被实例化和绑定的片段。

      我个人会更改处理页面片段内微调器的实现,因为它只作用于页面片段。

      使用 setUserVisibleHint 的解决方案

      当片段对用户可见时,将页面片段绑定到主片段。注意内存泄漏,释放静态引用

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

      公交车解决方案

      另一个快速的解决方案是使用这样的总线:http://square.github.io/otto/ 这样,每个片段都会订阅一个事件SelectedItemChanged 并自行刷新它们。每次更改微调器选择时,主片段都会发布更新。

      但是这个例子很大,所以我不太确定是否有其他问题。尝试分享一个完整的项目以获得更具体的帮助。

      【讨论】:

      • 没有变化。但是我发现选择微调器时数据列表不为空然后为空
      【解决方案4】:

      当您使用 recycleview 时,仅依赖于您的 模型类 字段值。对模型类进行所有更改并基于此模型类字段创建行视图。

      即,您必须根据模型类字段的值创建或更改值或查看状态。

      例如:如果你想让一行(位置 30)不可见,那么我将在模型类中设置一个名为 visibility 的标志并将其设置为 false

      在这种情况下,每当视图在 UI 中重绘时,我们都必须检查标志并根据该模型类字段值设置可见性。

      像这样,您可以在模型类中创建标志、内容值、来自 API 等的序列化参数。通过用户交互和 API 更改,此方法将使您的 recycleview 更加一致。

      【讨论】:

        【解决方案5】:

        检查您的StudentViewPagerAdapter

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

        你为什么又打电话给newInstance

        将其替换为以下内容, return mFragmentList.get(position);

        【讨论】:

        • 不,当我这样做时它会抛出 NullPointerException
        • 为什么?它不应该抛出 NullPointerException 对吗?这意味着您的 StudentViewPagerAdapter 初始化有一些错误
        • 你的意思是 StudentList 片段,我找不到你在 StudentList 类文件中引用'StudentViewPagerAdapter'
        • 避免嵌套 Fragments,在 Activity 中进行初始化,同时修复 NullPointerException。最美好的祝愿:)
        【解决方案6】:

        首先,检查你是否在

        之后添加了这一行
        setadapter :
        adapter.notifyDataSetChanged();
        

        另一种方法是使最终的MyViewHolder持有者和int位置

        例子。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-05
          • 1970-01-01
          • 2017-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多