android firebase : NOT EQUAL query in Firebase Database

后端 未结 2 569
不知归路
不知归路 2021-01-07 13:00

I have users object as below:

{
  \"deviceTokens\" : {
    \"SgJd7o1hK7YbJnygnYWvaz4qkr42\" : {
      \"c-sfcTB3iEA:APA91bEvuzhX1nlrhoxVmR69lvwu0H1zyRjOXd5b1         


        
相关标签:
2条回答
  • 2021-01-07 13:29

    Actually, I didn't wanted to create my own adapter, because I believed that FirebaseUI would not have such a limitation, but I was wrong. Anyways, this is how I approached:

    First of all fetch all the data from the User Object from FirebaseDatabase and then, filter on our end and finally, set that data:

    FirebaseDatabase.getInstance().getReference().child("users")
       .addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Iterable<DataSnapshot> list = dataSnapshot.getChildren();
    
                // Getting current user Id
                String uid = getCurrentUserId();
    
                // Filter User
                List<User> userList = new ArrayList<>();
                for (DataSnapshot dataSnapshot1 : list) {
                    if (!dataSnapshot1.getKey().equals(uid)) {
                        userList.add(dataSnapshot1.getValue(User.class));
                    }
                }
    
                // Setting data
                mBaseRecyclerAdapter.setItems(userList);
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
    
            }
        });
    

    I have created my own generic recycler adapter here: https://gist.github.com/chintansoni202/3c61aea787ae4bd49f26adee9dd40a08

    0 讨论(0)
  • 2021-01-07 13:33

    One way to solve this and still use FirebaseRecyclerAdapter from FirebaseUI is to extend FirebaseArray like this:

    import com.firebase.ui.database.FirebaseArray;
    import com.firebase.ui.database.SnapshotParser;
    import com.google.firebase.database.DataSnapshot;
    import com.google.firebase.database.Query;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class FilterableFirebaseArray extends FirebaseArray {
    
        private Set<String> excludes = new HashSet<>();
    
        public FilterableFirebaseArray(Query query, Class aClass) {
            super(query, aClass);
        }
    
        public FilterableFirebaseArray(Query query, SnapshotParser parser) {
            super(query, parser);
        }
    
        public void addExclude(String key) {
            excludes.add(key);
        }
    
        public void removeExclude(String key) {
            excludes.remove(key);
        }
    
        @Override
        public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
            if (!excludes.contains(snapshot.getKey())) {
                super.onChildAdded(snapshot, excludes.contains(previousChildKey)? null : previousChildKey);
            }
        }
    
        @Override
        public void onChildChanged(DataSnapshot snapshot, String previousChildKey) {
            if (!excludes.contains(snapshot.getKey())) {
                super.onChildChanged(snapshot, excludes.contains(previousChildKey)? null : previousChildKey);
            }
        }
    
        @Override
        public void onChildMoved(DataSnapshot snapshot, String previousChildKey) {
            if (!excludes.contains(snapshot.getKey())) {
                super.onChildMoved(snapshot, excludes.contains(previousChildKey)? null : previousChildKey);
            }
        }
    
        @Override
        public void onChildRemoved(DataSnapshot snapshot) {
            if (!excludes.contains(snapshot.getKey())) {
                super.onChildRemoved(snapshot);
            }
        }
    
    }
    

    …and then use it like this:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        RecyclerView userListView = (RecyclerView) findViewById(R.id.userList);
        userListView.setLayoutManager(new LinearLayoutManager(this));
    
        DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
        Query query = ref.orderByValue();
        ClassSnapshotParser parser = new ClassSnapshotParser<UserProfile>(UserProfile.class);
        FilterableFirebaseArray filterableFirebaseArray = new FilterableFirebaseArray(query, parser);
    
        filterableFirebaseArray.addExclude(FirebaseAuth.getInstance().getCurrentUser().getUid());
    
        FirebaseRecyclerAdapter mAdapter = new FirebaseRecyclerAdapter<UserProfile, UserListEntryHolder>(
                filterableFirebaseArray,
                R.layout.userlist_entry,
                UserListEntryHolder.class) {
            @Override
            protected void populateViewHolder(UserListEntryHolder viewHolder, UserProfile model, int position) {
                viewHolder.bind(model);
            }
        };
        userListView.setAdapter(mAdapter);
    }
    

    The "magic" happens in the overridden onChildAdded method where we ignore children identified by the specified keys. In this example I simply add the UID of the current user to the exclusion list. As this matches my database design.

    You could easily extend the functionality to ignore children with specific properties.

    Bonus: If you prefer the Kotlin way (like me) this is how you'd do it:

    import com.firebase.ui.database.FirebaseArray
    import com.firebase.ui.database.SnapshotParser
    import com.google.firebase.database.DataSnapshot
    import com.google.firebase.database.Query
    
    class FilterableFirebaseArray<T> : FirebaseArray<T> {
    
        val excludedKeys = HashSet<String?>()
    
        constructor(query: Query, tClass: Class<T>) : super(query, tClass)
        constructor(query: Query, parser: SnapshotParser<T>) : super(query, parser)
    
        override fun onChildAdded(snapshot: DataSnapshot, previousChildKey: String?) {
            if (!excludedKeys.contains(snapshot.key))
                super.onChildAdded(snapshot, if (excludedKeys.contains(previousChildKey)) null else previousChildKey)
        }
    
        override fun onChildChanged(snapshot: DataSnapshot, previousChildKey: String?) {
            if (!excludedKeys.contains(snapshot.key))
                super.onChildChanged(snapshot, previousChildKey)
        }
    
        override fun onChildMoved(snapshot: DataSnapshot, previousChildKey: String?) {
            if (!excludedKeys.contains(snapshot.key))
                super.onChildMoved(snapshot, previousChildKey)
        }
    
        override fun onChildRemoved(snapshot: DataSnapshot) {
            if (!excludedKeys.contains(snapshot.key))
                super.onChildRemoved(snapshot)
        }
    
    }
    

    …and then use it like this:

    override fun onStart() {
        super.onStart()
        if (currentUser != null) {
            userList.adapter = getAdapter()
        }
    }
    
    private fun getAdapter(): FirebaseRecyclerAdapter<UserProfile, UserListEntryHolder> {
    
        val query = userProfilesReference.orderByValue()
        val parser = ClassSnapshotParser<UserProfile>(UserProfile::class.java)
        val filterableFirebaseArray = FilterableFirebaseArray<UserProfile>(query, parser)
    
        filterableFirebaseArray.excludes.add(currentUser?.uid)
    
        return object : FirebaseRecyclerAdapter<UserProfile, UserListEntryHolder>(
                filterableFirebaseArray,
                R.layout.userlist_entry,
                UserListEntryHolder::class.java) {
            public override fun populateViewHolder(entryHolder: UserListEntryHolder, userProfile: UserProfile, position: Int) {
                entryHolder.bind(userProfile)
            }
        }
    }
    

    Updated code to resolve IllegalArgumentExceptions related to onChildChanged, onChildMoved etc.

    0 讨论(0)
提交回复
热议问题