首页 > 解决方案 > SwipeRefreshLayout 无需下拉即可刷新 RecyclerView

问题描述

我正在尝试在SwipeRefreshLayout我的应用程序中实现一个。我想要发生的是,当用户最初打开应用程序时,数据是从 Firebase 检索的,而无需拉下布局以便数据刷新。之后,如果用户想要查看新数据,他们必须拉下布局,以便RecyclerView刷新其他用户上传的新帖子。

我遇到的问题是,当我从模拟器上传帖子时,它会自动在我的手机屏幕上弹出,而无需我下拉。那不是我想要的。首先,应自动检索应用程序数据的初始打开,而无需下拉。之后,每次您想查看新数据时,如果我转到不同的片段然后回来,除非我下拉,否则数据不应该刷新。

我目前拥有的代码如下。有人能告诉我为什么它没有按照我想要的方式工作吗?

我相对确定这是因为notifyDataSetChanged();我的readPosts();方法,但我不确定如何修复它...我应该将它从中删除并将其readPosts();添加到mSwipeRefreshLayout.post...Runnable

首页片段

public class HomeTabLayoutFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

    private ProgressBar mProgressBar;
    private PostAdapter mPostAdapter;
    private List<Post> mPostLists;

    private FirebaseAuth mFirebaseAuth;
    private FirebaseUser mFirebaseUser;

    private List<String> mFollowingList;

    private SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_home_tab_layout, container, false);

        mFirebaseAuth = FirebaseAuth.getInstance();
        mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();

        mProgressBar = v.findViewById(R.id.progress_circular);

        RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setReverseLayout(true);
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        mPostLists = new ArrayList<>();
        mPostAdapter = new PostAdapter(getContext(), mPostLists);
        recyclerView.setAdapter(mPostAdapter);

        mSwipeRefreshLayout = v.findViewById(R.id.refresh);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.post(() -> {
            mSwipeRefreshLayout.setRefreshing(true);
            readPosts();
        });

        checkIfUserExists();
        checkFollowing();

        return v;
    }

    @Override
    public void onRefresh() {
        readPosts();
    }

    private void checkIfUserExists() {
        if (mFirebaseAuth == null) {
            Intent intent = new Intent(getContext(), RegisterActivity.class);
            startActivity(intent);
        }
    }

    private void checkFollowing() {
        mFollowingList = new ArrayList<>();
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Follow").child(mFirebaseUser.getUid()).child("Following");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                mFollowingList.clear();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    mFollowingList.add(snapshot.getKey());
                }

                readPosts();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }

    private void readPosts() {
        mSwipeRefreshLayout.setRefreshing(true);
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                mPostLists.clear();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Post post = snapshot.getValue(Post.class);
                    if (post != null && shouldAddPost(post)) {
                        mPostLists.add(post);
                    }
                }

                mPostAdapter.notifyDataSetChanged();
                mProgressBar.setVisibility(View.GONE);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        mSwipeRefreshLayout.setRefreshing(false);
    }

    private boolean shouldAddPost(@NotNull Post post) {
        boolean isFollowingPublisher = false;
        for (String id : mFollowingList) {
            if (post.getPublisher().equals(id)) {
                isFollowingPublisher = true;
                break;
            }
        }

        boolean isPublisher = post.getPublisher().equals(mFirebaseUser.getUid());

        return isFollowingPublisher || isPublisher;
    }
}

标签: javaandroidandroid-recyclerviewswiperefreshlayout

解决方案


那是因为您使用的是addValueEventListener. 在这种情况下,ValueEventListener每次在此层次结构中进行任何更改时都会调用 a。

如果您只需要一次数据,则应该使用addListenerForSingleValueEvent。换句话说,如果您不想对节点进行实时更新,那么您可以使用addListenerForSingleValueEvent.

->回答关于mSwipeRefreshLayout.setRefreshing(false)定位在里面readPost

现在你怎么加mSwipeRefreshLayout.setRefreshing(true)mSwipeRefreshLayout.setRefreshing(false)其实没用。它会立即调用.. 你应该做的是改变监听器内部的状态。

private void readPosts() {
    mSwipeRefreshLayout.setRefreshing(true);
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mPostLists.clear();
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
            Post post = snapshot.getValue(Post.class);
            if (post != null && shouldAddPost(post)) {
                mPostLists.add(post);
            }
        }
            mPostAdapter.notifyDataSetChanged();
            mProgressBar.setVisibility(View.GONE);
            mSwipeRefreshLayout.setRefreshing(false);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            mSwipeRefreshLayout.setRefreshing(false);
        }
    });

推荐阅读