-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Prep for final refactors #1188
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
Prep for final refactors #1188
Conversation
Signed-off-by: Alex Saveau <[email protected]>
Signed-off-by: Alex Saveau <[email protected]>
Signed-off-by: Alex Saveau <[email protected]>
private String mMessage; | ||
|
||
static { | ||
boolean log; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh this is a neat but also kind of nasty trick. Did you see this somewhere else? Reflection in a static block seems like it could really slow down some startup times.
Maybe we should just add a FirebaseUI.setLogLevel method or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I just noticed that some exceptions had sensitive info like emails and whatnot that we shouldn't be logging in production. I'll put this on the TODO list for later to figure out. 👍
throw new AssertionError("No instance for you!"); | ||
} | ||
|
||
public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am totally fine with this, but do you think it makes sense to just have all of our Resource
s return a common exception class with a code
and a cause
and then we could just switch on code
instead of using instanceof
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to, but we already have code that sets the failure to task.getException()
. I'm not sure if we'd want to wrap everything in a FirebaseUiException
, but that would definitely make this stuff cleaner. Ideas?
private CredentialsClient mCredentialsClient; | ||
private FirebaseAuth mAuth; | ||
private PhoneAuthProvider mPhoneAuth; | ||
|
||
private SingleLiveEvent<PendingResolution> mPendingResolution = new SingleLiveEvent<>(); | ||
private MutableLiveData<Resource<T>> mOperation = new MutableLiveData<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you quickly explain how you're mitigating the risk that comes with removing the SingleLiveEvent
for the errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You got it below, it's the setUsed
thing. I'm totally open to going back to our SingleLiveEvent
, but that felt like the greater of the two evils. Thoughts?
This looks really great! I wonder: can/should we enforce that But maybe that's not the case? Either way it would be good to know/define. |
Signed-off-by: Alex Saveau <[email protected]>
if (!(e instanceof StatefulException) || ((StatefulException) e).isUsed()) { | ||
return false; | ||
} | ||
((StatefulException) e).setUsed(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the setUsed
could be automatically called inside getPendingIntent()
or getIntent()
so that way you can really only get them once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I actually did that to start but it felt kinda weird. If you had that idea too, then it can't be that weird. 😆 SGTM!
Signed-off-by: Alex Saveau <[email protected]>
@samtstern For the resource stuff, |
Signed-off-by: Alex Saveau <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very few remaining comments! Looking good.
|
||
public class StatefulException extends FirebaseUiException { | ||
public StatefulException() { | ||
super(ErrorCodes.UNKNOWN_ERROR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So do we need this class anymore if it doesn't actually hold any state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, good catch!
if (!mHandler.onActivityResult(requestCode, resultCode, data)) { | ||
super.onActivityResult(requestCode, resultCode, data); | ||
} | ||
super.onActivityResult(requestCode, resultCode, data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure there's no issue unconditionally calling both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, as long as we have different request codes (we do: 100 and 101). I felt like we'd get nipped in the behind later if onActivityResult
was called non-deterministically. (Especially since fragments rely on that call.)
} | ||
|
||
public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { | ||
if (!(e instanceof StatefulException)) { return false; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that StatefulException
is really a useful / meaningful base class (as stated in a comment above). Why not just return true
inside each of the if
blocks and then return false
at the end otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree, been there, done that. 👍😆
ArgumentCaptor<PendingResolution> resolveCaptor = ArgumentCaptor.forClass(PendingResolution.class); | ||
verify(mResolutionObserver).onChanged(resolveCaptor.capture()); | ||
ArgumentCaptor<Resource<Void>> resolveCaptor = ArgumentCaptor.forClass(Resource.class); | ||
verify(mResultObserver, times(2)).onChanged(resolveCaptor.capture()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change the test to actually verify the onChanged
events separately? Kind of confusing to verify that the second time is a PendingIntentRequiredException
but we don't assert/care what the first event is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do below but I got an exception without the times(2)
. Is there a prettier way to do this with mockito?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for learning purposes (I am fine with your code) you can tell Mockito you want to do events in order.
Here is some code from another project of mine which is basically the same (over there we call Resource
a Loadable
):
// Verify order of events
InOrder inOrder = Mockito.inOrder(loadingObserver);
// Start by loading
liveData.postValue(Loadable.forLoading());
inOrder.verify(loadingObserver).onChanged(true);
// Move to success
liveData.postValue(Loadable.forSuccess("Hello"));
inOrder.verify(loadingObserver).onChanged(false);
// Make sure that double-success does not make the observer get called again
liveData.postValue(Loadable.forSuccess("This should have never been posted"));
inOrder.verify(loadingObserver, never()).onChanged(anyBoolean());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoa, that looks super cool!
Just for learning purposes
Says you, I definitely using that! 😆 Thanks for tip 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Want me to merge-as is or do you want to go and use InOrder
? Up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay, my laptop died in the middle of running tests. 😭😆 Anyway, it's much prettier now!
Signed-off-by: Alex Saveau <[email protected]>
Signed-off-by: Alex Saveau <[email protected]>
@samtstern Alrighty, it's time to plow through that refactor!
This PR makes a few core changes:
LiveData
s every time. I think that makes the most sense, what are your thoughts?LiveData
for all subclasses to interact with.