简体   繁体   English

SwipeRefreshLayout 无需下拉即可刷新 RecyclerView

[英]SwipeRefreshLayout refreshes RecyclerView without having to pull down

I am trying to implement an SwipeRefreshLayout into my app.我正在尝试在我的应用程序中实现SwipeRefreshLayout What I want to happen is that when the user opens the app initially that the data is retrieved from Firebase without having to pull down the layout so the data refreshes.我想要发生的是,当用户最初打开应用程序时,数据是从 Firebase 检索的,而无需拉下布局以便数据刷新。 After that, if the user wants to see new data they have to pull down the layout so the RecyclerView is refreshed with new posts that other users have uploaded.之后,如果用户想要查看新数据,他们必须拉下布局,以便RecyclerView刷新其他用户上传的新帖子。

The problem that I am running into is that when I upload a post from my emulator it pops up on screen automatically on my phone without me having to pull down.我遇到的问题是,当我从模拟器上传帖子时,它会自动在我的手机屏幕上弹出,而无需我下拉。 That's not what I want.那不是我想要的。 First, initial opening of app data should be retrieved automatically without pull down.首先,应自动检索应用程序数据的初始打开,而无需下拉。 After that, every time you want to see new data, if I go to a different fragment and then come back the data shouldn't be refreshed unless I pull down.之后,每次您想查看新数据时,如果我将 go 转到不同的片段然后返回数据不应该刷新,除非我下拉。

The code that I have currently is the following.我目前拥有的代码如下。 Can someone tell me why it isn't working the way that I would like it to?有人能告诉我为什么它没有按照我想要的方式工作吗?

I am relatively sure that it's because of my notifyDataSetChanged();我比较确定这是因为我的notifyDataSetChanged(); in my readPosts();在我的readPosts(); method, but I'm not sure how to fix it... Should I just remove it from readPosts();方法,但我不确定如何修复它......我应该将它从readPosts();中删除吗? and add it to the mSwipeRefreshLayout.post...Runnable ?并将其添加到mSwipeRefreshLayout.post...Runnable

HomeFragment首页片段

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

That is because you are using a addValueEventListener .那是因为您使用的是addValueEventListener In this case a ValueEventListener will get called each time any changes made in this hierarchy.在这种情况下,每次在此层次结构中进行任何更改时都会调用ValueEventListener

You should be using addListenerForSingleValueEvent if you want data only once.如果您只需要一次数据,则应该使用addListenerForSingleValueEvent In other words if you do not want realtime updates for a node then you use addListenerForSingleValueEvent .换句话说,如果您不想对节点进行实时更新,那么您可以使用addListenerForSingleValueEvent

->Answer about mSwipeRefreshLayout.setRefreshing(false) positioning inside readPost . -> 回答mSwipeRefreshLayout.setRefreshing(false)readPost中的定位。

Right now how you added mSwipeRefreshLayout.setRefreshing(true) and mSwipeRefreshLayout.setRefreshing(false) is actually useless.现在你如何添加mSwipeRefreshLayout.setRefreshing(true)mSwipeRefreshLayout.setRefreshing(false)实际上是没用的。 It will call immediately.. What you should be doing is changing the state inside listeners.它会立即调用.. 您应该做的是更改侦听器内部的 state。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM