Skip to content

Add a callback in FirebaseIndexArray when a Key doesn't exist in a ref #448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 47 commits into from
Closed

Conversation

SUPERCILEX
Copy link
Collaborator

@SUPERCILEX SUPERCILEX commented Dec 9, 2016


import com.google.firebase.database.DataSnapshot;

interface OnIndexMismatchListener {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the On prefix, to align with existing Firebase listeners: ValueEventListener, ChildEventListener.

I'm not really convinced of this class name. It's very specific to this use-case, while we might uncover other use-cases in the future that could use this same interface. If the snapshot is from the originating/key collection, I can see this interface defining a "join this data" contract.

Could we change the behavior from an error to an "override point". So instead of this being the error condition, make it the regular handler for joins? interface JoinResolver, that developers can then implement/override to have their own join/error handling? Thoughts? @SUPERCILEX @samtstern @morganchen12

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@puf, so were you thinking of something like this:

@Override
public void onChildAdded(DataSnapshot keySnapshot, String previousChildKey) {
    // ...
    Query ref = mJoinResolver.onJoin(keySnapshot); // Get the data ref
    mRefs.put(ref, ref.addValueEventListener(new DataRefListener()));
}

@Override
public void onChildRemoved(DataSnapshot keySnapshot) {
    Query removeQuery = mJoinResolver.onDisjoin(keySnapshot); // Get the remove ref
    removeQuery.removeEventListener(mRefs.remove(removeQuery));
    // ...
}
private class DataRefListener implements ValueEventListener {
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        if (snapshot.getValue() != null) {
            // ...
        } else {
            if (isMatch(index, key)) {
               // ...
            } else {
                mJoinResolver.onJoinFailed(index, snapshot); // notify failure
            }
        }
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. That first snippet looks like it. Not sure about the second snippet though. What would the mJoinResolver consist of there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@puf the second snippet is occurs when dataRef returns a null snapshot. The original purpose of this PR was to change that piece of code from a log (Log.w(TAG, "Key not found at ref: " + snapshot.getRef());) to a callback. Is it still okay to follow through with mJoinResolver.onJoinFailed(index, snapshot);?

Copy link
Collaborator Author

@SUPERCILEX SUPERCILEX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@puf It turned out to be more complicated than I thought so this PR is pretty big now, sorry.

I found out today that you can't pass in this while initializing a super constructor. Because of this I had to follow the setter pattern for JoinResolver, but this makes future open sourcing of FirebaseIndexArray and any current implementations unacceptable because people will think that setting a JoinResolver is optional and we would not be able to get the join query. Also, how do we know an onChildAdded event won't be called between the time when we start listening for event and when the JoinResolver is set? To solve this problem, I pretty significantly changed FirebaseArray and FirebaseIndexArray's apis (thank the api god we didn't open source FirebaseArray yet! 😄). Both FirebaseArray and FirebaseIndexArray now follow a start stop pattern like the activity lifecycle: you create stuff and then tear it down. In addition, listeners are no longer optional because a FirebaseArray that never reports back its results is pointless. I made what I believe to be a really nice api (@puf I'd love your thoughts on this!) where you can setup your listeners and then start listening for events once your ready. If you so choose, you may also stop listening for events in effect resetting FirebaseArray. However, the listeners and queries are still present which enables resuming listening at a later time. To prevent errors, all of this is cross checked.

I think my changes make FirebaseArray and FirebaseIndexArray much more ready for open sourcing with nicer apis, @puf what are your thoughts on these changes?

@@ -0,0 +1,41 @@
package com.firebase.uidemo.database;

public class Chat {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted Chat and ChatHolder to simplify ChatActivity.

chatView.setName(chat.getName());
chatView.setText(chat.getMessage());
mRecyclerViewAdapter =
new FirebaseIndexRecyclerAdapter<Chat, ChatHolder>(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because FirebaseIndexRecyclerAdapter is slightly more complicated and less documented, I think we should demo that in the sample.

attachRecyclerViewAdapter();
}
})
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making the Toast survive activity rotation.

@@ -26,69 +28,72 @@
* This class implements an array-like collection on top of a Firebase location.
*/
class FirebaseArray implements ChildEventListener {
public interface OnChangedListener {
public interface ChangeEventListener {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the name to follow ChildEventListener.

}

public int getCount() {
public int size() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed getCount and getItem to follow array naming conventions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like pretty breaking changes, but I'm only just someone really curious about this project.
Also, was a consensus ever reached on using enums in the code? Shouldn't we be doing something like this:

public interface ChangeListener {
    public static class EventType {
        public static final int ADDED = 1;
        public static final int CHANGED = 2;
        // ...
    }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheCraftKid Nope, these aren't breaking api changes. 🎉 We're really lucky @puf wanted to hold out on open sourcing FirebaseArray and FirebaseIndexArray or these would have been (You're thinking of FirebaseRecyclerViewAdapter#getItemCount(), but I didn't change that.)

As for enums, @puf decided against it and I'm fine with that because I found out proguard usually converts enums to ints anyway: http://stackoverflow.com/a/32236950/4548500. Cheers!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, then.
Wait, FirebaseArray is being open-sourced? How will that work? Will I finally be able to implement a proper FirebaseSpinnerAdapter?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woah woah woah! 😄 I was just saying that eventually @puf will have to open source it (technically he doesn't, but come on!). I think he was waiting for some additional refinement and this PR + another one I have ready will clean things up a bit, making it more likely that FirebaseArray will be open sourced. Then yes, you will finally be able to implement a proper FirebaseSpinnerAdapter!


Query ref = mQuery.getRef().child(keySnapshot.getKey());
Query ref = mJoinResolver.onJoin(keySnapshot, previousChildKey);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the new JoinResolver.

@@ -82,6 +88,24 @@ public FirebaseIndexRecyclerAdapter(Class<T> modelClass,
Class<VH> viewHolderClass,
Query keyRef,
Query dataRef) {
super(modelClass, modelLayout, viewHolderClass, new FirebaseIndexArray(keyRef, dataRef));
super(modelClass, modelLayout, viewHolderClass, new FirebaseIndexArray(keyRef), false);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, I can't just pass in new FirebaseIndexArray(keyRef, this).

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.Query;

public interface JoinResolver {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on the documentation?

@puf
Copy link
Contributor

puf commented Dec 19, 2016 via email

@SUPERCILEX
Copy link
Collaborator Author

@puf I meant making FirebaseArray a public class so people can use it without having to copy it.

Signed-off-by: Alex Saveau <[email protected]>
Signed-off-by: Alex Saveau <[email protected]>
…lback

# Conflicts:
#	app/src/main/java/com/firebase/uidemo/database/ChatActivity.java
#	database/src/main/java/com/firebase/ui/database/FirebaseArray.java
#	database/src/main/java/com/firebase/ui/database/FirebaseListAdapter.java
#	database/src/main/java/com/firebase/ui/database/FirebaseRecyclerAdapter.java
Signed-off-by: Alex Saveau <[email protected]>
# Conflicts:
#	database/src/androidTest/java/com/firebase/ui/database/TestUtils.java
@SUPERCILEX SUPERCILEX changed the base branch from version-1.1.0-dev to master January 17, 2017 20:43
@SUPERCILEX SUPERCILEX changed the base branch from master to version-1.2.0-dev January 24, 2017 00:15
…lback

# Conflicts:
#	app/src/main/java/com/firebase/uidemo/database/ChatActivity.java
#	database/src/androidTest/java/com/firebase/ui/database/TestUtils.java
#	database/src/main/java/com/firebase/ui/database/FirebaseArray.java
#	database/src/main/java/com/firebase/ui/database/FirebaseIndexArray.java
#	database/src/main/java/com/firebase/ui/database/FirebaseListAdapter.java
#	database/src/main/java/com/firebase/ui/database/FirebaseRecyclerAdapter.java
Signed-off-by: Alex Saveau <[email protected]>
…lback

# Conflicts:
#	app/src/main/java/com/firebase/uidemo/database/ChatActivity.java
#	database/src/androidTest/java/com/firebase/ui/database/FirebaseArrayOfObjectsTest.java
#	database/src/androidTest/java/com/firebase/ui/database/FirebaseArrayTest.java
#	database/src/androidTest/java/com/firebase/ui/database/FirebaseIndexArrayOfObjectsTest.java
#	database/src/androidTest/java/com/firebase/ui/database/FirebaseIndexArrayTest.java
#	database/src/androidTest/java/com/firebase/ui/database/TestUtils.java
#	database/src/main/java/com/firebase/ui/database/FirebaseArray.java
#	database/src/main/java/com/firebase/ui/database/FirebaseIndexArray.java
#	database/src/main/java/com/firebase/ui/database/FirebaseIndexRecyclerAdapter.java
#	database/src/main/java/com/firebase/ui/database/FirebaseListAdapter.java
#	database/src/main/java/com/firebase/ui/database/FirebaseRecyclerAdapter.java
Signed-off-by: Alex Saveau <[email protected]>
@googlebot
Copy link

So there's good news and bad news.

👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there.

😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request.

Note to project maintainer: This is a terminal state, meaning the cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

@SUPERCILEX SUPERCILEX changed the base branch from version-1.2.0-dev to version-2.0.0-dev March 6, 2017 20:34
Signed-off-by: Alex Saveau <[email protected]>
@googlebot
Copy link

CLAs look good, thanks!

@SUPERCILEX
Copy link
Collaborator Author

@samtstern Should we add extra constructors in the index adapters? I feel like this is a niche feature and people who use it will know how to pass in a FirebaseIndexArray to the FirebaseRecyclerAdapter. What do you think?

@SUPERCILEX
Copy link
Collaborator Author

@samtstern While we're on the merge rollercoaster, I think this one is the next PR to take a look at. 😄

@samtstern
Copy link
Contributor

@SUPERCILEX I agree, this one is definitely next. I will take a look tomorrow. A lot has changed in how we handle the IndexedArray (and really everything) since this was first sent out.

Btw we really appreciate that you always keep these PRs up to date and you're ready to discuss when we find the time. It's above-and-beyond as a contributor and arguably we have not earned it since we go radio silent too often.

@SUPERCILEX
Copy link
Collaborator Author

SUPERCILEX commented Apr 26, 2017

@samtstern No problem, I'm just happy whenever the ball moves forward a bit! 😄

Yeah, this was actually the PR that got me started on the whole "Let's redo firebase-ui-database" thing. The funniest part is that it's not even a feature I use in my app. 😆

@SUPERCILEX SUPERCILEX changed the base branch from version-2.0.0-dev to version-2.1.0-dev June 13, 2017 02:05
@SUPERCILEX
Copy link
Collaborator Author

Going to close this PR since there is very little demand and it isn't on the FirebaseUI roadmap.

@SUPERCILEX SUPERCILEX closed this Jul 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants