首页 > 解决方案 > 无法在返回导航时维护 Firestore RecyclerView 状态

问题描述

我有一个包含 Recyclerview 的片段。此 RecyclerView 使用 Firebase FirestoreUI 填充。

下面是我的 RecyclerView 的代码,我在 .onStart() 中调用它来监听变化:

@Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (savedInstanceState != null) {
            mRecyclerViewState = savedInstanceState.getParcelable(RECYCLERVIEW_STATE);
        }
        mRecyclerview = (RecyclerView) view.findViewById(R.id.list);
        mPollHolderArray = new ArrayList<>();
        mRecyclerview.getItemAnimator().setChangeDuration(0);


        mLayoutManager = new LinearLayoutManager(getContext());
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        //TODO: Detertmine if necessary since ordering is now different in Firebase
        mLayoutManager.setReverseLayout(true);
        mLayoutManager.setStackFromEnd(true);

        mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
        mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
                startActivity(I);
            }
        });


        mRecyclerview.setLayoutManager(mLayoutManager);

        if (mRecyclerViewState != null){
            mLayoutManager.onRestoreInstanceState(mRecyclerViewState);
        }


        if (mFirestoreAdaper == null) {
            Query queryStore = FirebaseFirestore.getInstance()
                    .collection(POLLS_LABEL)
                    .orderBy("timestamp", Query.Direction.ASCENDING);
            //Cloud Firestore does not have any ordering; must implement a timestampe to order sequentially

            FirestoreRecyclerOptions<Poll> storeOptions = new FirestoreRecyclerOptions.Builder<Poll>()
                    .setQuery(queryStore, Poll.class)
                    .build();
            mFirestoreAdaper = new FirestoreRecyclerAdapter<Poll, PollHolder>(storeOptions) {
                @Override
                protected void onBindViewHolder(@NonNull final PollHolder holder, final int position, @NonNull Poll model) {
                    holder.mPollQuestion.setText(model.getQuestion());
                    String voteCount = String.valueOf(model.getVote_count());
                    //TODO: Investigate formatting of vote count for thousands
                    holder.mVoteCount.setText(voteCount);
                    Picasso.get()
                            .load(model.getImage_URL())
                            .fit()
                            .into(holder.mPollImage);
                    holder.mView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Intent toClickedPoll = new Intent(getActivity(), PollHostActivity.class);
                            String recyclerPosition = getSnapshots().getSnapshot(position).getId();
                            Log.v("Firestore ID", recyclerPosition);
                            toClickedPoll.putExtra("POLL_ID", recyclerPosition);
                            startActivity(toClickedPoll);

                        }
                    });
                }


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


            };
            mRecyclerview.setAdapter(mFirestoreAdaper);
        }
    }

当我导航到另一个 Fragment(RecyclerView 的 onClick),然后返回到包含此 RecyclerView 的 Fragment 时,我希望能够保持被单击的位置。然而,这并没有发生。下面是我尝试保存状态的代码,它只是恢复到 RecyclerView 的顶部项目:

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    mRecyclerViewState = mLayoutManager.onSaveInstanceState();
    outState.putParcelable(RECYCLERVIEW_STATE, mRecyclerViewState);

}

编辑:原始片段是 ViewPager 的一部分(我现在正在 NewFragment 上对其进行测试):

    public class SectionPagerAdapter extends FragmentPagerAdapter {

    public SectionPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new TrendingFragment();
            case 1:
                return new FollowingFragment();
            case 2:
                return new NewFragment();
            default:
                return new TrendingFragment();
        }
    }

标签: javaandroidfirebaseandroid-recyclerview

解决方案


那是因为您在 中设置了新适配器onStart,并且每当您从前一个屏幕或背景恢复片段时都会发生这种情况。

您不需要所有这些逻辑来帮助记住位置,您只需在生命周期内初始化并将适配器设置在正确的位置。

在您的片段中,将您的适配器设置onViewCreatedonStart

@Override public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mRecyclerview = view.findViewById(...);
    if (mAdapter == null) {
        mAdapter = new FirestoreRecyclerAdapter(...)
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.startListening();
    }
}

@Override public void onDestroyView() {
    super.onDestroyView();
    mAdapter.stopListening();
}

并删除所有保存和恢复位置的逻辑(onSaveInstanceState, scrollToPosition, onRestoreInstanceState),您不需要它们!


推荐阅读