So basically what I'm trying to do is, make a first network call. And if the called RESTful web service returns 1, make a second network call. If the web service returns 0, then do not make the second network call.
Here's my code
final ApiInterface apiInterface=restAdapter.create(ApiInterface.class);
apiInterface.submitDataToAnalyze("dataToAnalyze","852741963",1,"123","lalala","2015-11-20")
.flatMap(new Func1<BasicResponse, Observable<?>>() {
#Override
public Observable<?> call(BasicResponse basicResponse) {
if (basicResponse.getResult() == 1){
return apiInterface.getSuggestion("dataToAnalyze","852741963",1,"123","lalala","2015-11-20");
}else{
return 0; //error
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
Obviously the code above is wrong, since it should always return Observable. So how should my code be written, if the first network call returns 0?
I think the best practice is to return Observable.error(new Throwable("..."))
taken from the javadoc :
/**
* Returns an Observable that invokes an {#link Observer}'s {#link Observer#onError onError} method when the
* Observer subscribes to it.
* <p>
* <img width="640" height="190" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/error.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{#code error} does not operate by default on a particular {#link Scheduler}.</dd>
* </dl>
*
* #param exception
* the particular Throwable to pass to {#link Observer#onError onError}
* #param <T>
* the type of the items (ostensibly) emitted by the Observable
* #return an Observable that invokes the {#link Observer}'s {#link Observer#onError onError} method when
* the Observer subscribes to it
* #see ReactiveX operators documentation: Throw
*/
Related
I am asking this because of the confusion about the created state:
From docs on onCreate():
You must implement this callback, which fires when the system first creates the activity. On activity creation, the activity enters the Created state. In the onCreate() method, you perform basic application startup logic that should happen only once for the entire life of the activity.
It raises following questions:
Does the CREATED state occur before or after the call to onCreate()?
Is the CREATED state constant used below different from the theoretical meaning of state being defined in the above excerpt, i.e, I should just read this and move on not focusing on the created state phrase?
Before you answer, there is the Lifecycle.State class from Lifecycle Aware components where in you can see the meaning of various states as follows:
/**
* Lifecycle states. You can consider the states as the nodes in a graph and
* {#link Event}s as the edges between these nodes.
*/
#SuppressWarnings("WeakerAccess")
public enum State {
/**
* Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
* any more events. For instance, for an {#link android.app.Activity}, this state is reached
* <b>right before</b> Activity's {#link android.app.Activity#onDestroy() onDestroy} call.
*/
DESTROYED,
/**
* Initialized state for a LifecycleOwner. For an {#link android.app.Activity}, this is
* the state when it is constructed but has not received
* {#link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
*/
INITIALIZED,
/**
* Created state for a LifecycleOwner. For an {#link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {#link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
* <li><b>right before</b> {#link android.app.Activity#onStop() onStop} call.
* </ul>
*/
CREATED,
/**
* Started state for a LifecycleOwner. For an {#link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {#link android.app.Activity#onStart() onStart} call;
* <li><b>right before</b> {#link android.app.Activity#onPause() onPause} call.
* </ul>
*/
STARTED,
/**
* Resumed state for a LifecycleOwner. For an {#link android.app.Activity}, this state
* is reached after {#link android.app.Activity#onResume() onResume} is called.
*/
RESUMED;
/**
* Compares if this State is greater or equal to the given {#code state}.
*
* #param state State to compare with
* #return true if this State is greater or equal to the given {#code state}
*/
public boolean isAtLeast(#NonNull State state) {
return compareTo(state) >= 0;
}
}
I would like to believe the CREATED state occurs after the call to onCreate() because CREATED implies that at that moment it already has been created while onCreate() as from the name implies it is under creation for now and the comment in the Lifecycle.State class implies the same for CREATED state.
So to conclude:
onCreate() -> Under the process of creation
CREATED -> Already has finished the process of creation
The comment from LifeCycle state implies same as said
/**
* Created state for a LifecycleOwner. For an {#link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {#link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
* <li><b>right before</b> {#link android.app.Activity#onStop() onStop} call.
* </ul>
I have tried to implement a custom MaterialDatePicker calendar, but this method asks for a DateSelector, and I ask what is a DateSelector?
/**
* Sets the Builder's selection manager to the provided {#link DateSelector}.
*
* #hide
*/
#RestrictTo(LIBRARY_GROUP)
#NonNull
public static <S> Builder<S> customDatePicker(#NonNull DateSelector<S> dateSelector) {
return new Builder<>(dateSelector);
}
This says the description of the Interface DateSelector
/**
* Interface for users of {#link MaterialCalendar<S>} to control how the Calendar displays and
* returns selections.
*
* <p>Implementors must implement {#link Parcelable} so that selection can be maintained through
* Lifecycle events (e.g., Fragment destruction).
*
* <p>Dates are represented as times in UTC milliseconds.
*
* #param <S> The type of item available when cells are selected in the {#link AdapterView}
* #hide
*/
I'm having trouble testing my navigation with NavigationComponent, Espresso and Mockito. I have this simple test:
#Test
fun testNavigation(){
val mockNavController = mock(NavController::class.java)
val firstScenario = launchFragmentInContainer<FirstFragment>()
firstScenario.onFragment { fragment ->
Navigation.setViewNavController(fragment.requireView(), mockNavController)
}
val expectedBundle = bundleOf(ARG_A to true)
onView(withId(R.id.button)).perform(click())
verify(mockNavController).navigate(R.id.action_first_fragment_to_second_fragment, expectedBundle)
}
The test fails with this error:
Argument(s) are different! Wanted:
navController.navigate(
2131361850,
Bundle[{ARG_A=true}]
);
-> at FirstFragmentTest.testNavigation(FirstFragmentTest.kt:60)
Actual invocation has different arguments:
navController.navigate(
2131361850,
Bundle[{ARG_A=true}]
);
-> at FirstFragment$onViewCreated$2.onClick(FirstFragment.kt:67)
The arguments and id are exactly the same, the only difference is that last line in the error showing where the on click was invoked. Also, the onClick() method in my test doesn't even seem to open the second fragment. It just stays on the first fragment.
Does someone know what's going wrong?
Thanks in advance!
Bundles can contain different kinds of information, of different types and sizes.
equals method of Bundle class is just default implementation that compares two objects by reference.
You'll have to implement comparison by yourself or use already approved solution.
I've found a static method of Bundle superclass BaseBundle called kindOfEquals:
/**
* Does a loose equality check between two given {#link BaseBundle} objects.
* Returns {#code true} if both are {#code null}, or if both are equal as per
* {#link #kindofEquals(BaseBundle)}
*
* #param a A {#link BaseBundle} object
* #param b Another {#link BaseBundle} to compare with a
* #return {#code true} if both are the same, {#code false} otherwise
*
* #see #kindofEquals(BaseBundle)
*
* #hide
*/
public static boolean kindofEquals(BaseBundle a, BaseBundle b) {
return (a == b) || (a != null && a.kindofEquals(b));
}
But because it does loose equality check that may be not the desired solution.
Update
BaseBundle is not public but you can still check its kindOfEquals implementation and take it as an example.
I don't understand the documentation of the deflect method, can you please explain it to me in better words and with example if you can.
/**
* Instructs this {#link #STATE_RINGING} {#code Call} to deflect.
*
* #param address The address to which the call will be deflected.
*/
public void deflect(Uri address) {
mInCallAdapter.deflectCall(mTelecomCallId, address);
}
public abstract class SupportAnimator extends Animator {
WeakReference<RevealAnimator> mTarget;
public SupportAnimator(RevealAnimator target) {
mTarget = new WeakReference<>(target);
}
/**
* #return true if using native android animation framework, otherwise is
* nineoldandroids
*/
public abstract boolean isNativeAnimator();
/**
* #return depends from {#link android.os.Build.VERSION} if sdk version
* {#link android.os.Build.VERSION_CODES#LOLLIPOP} and greater will
* return {#link android.animation.Animator}
*/
public abstract Object get();
/**
* Starts this animation. If the animation has a nonzero startDelay, the
* animation will start running after that delay elapses. A non-delayed
* animation will have its initial value(s) set immediately, followed by
* calls to
* {#link android.animation.Animator.AnimatorListener#onAnimationStart(android.animation.Animator)}
* for any listeners of this animator.
*
* <p>
* The animation started by calling this method will be run on the thread
* that called this method. This thread should have a Looper on it (a
* runtime exception will be thrown if this is not the case). Also, if the
* animation will animate properties of objects in the view hierarchy, then
* the calling thread should be the UI thread for that view hierarchy.
* </p>
*
*/
public abstract void start();
/**
* Adds a listener to the set of listeners that are sent events through the
* life of an animation, such as start, repeat, and end.
*
* #param listener
* the listener to be added to the current set of listeners for
* this animation.
*/
public abstract void addListener(AnimatorListener listener);
/**
* Returns whether this Animator is currently running (having been started
* and gone past any initial startDelay period and not yet ended).
*
* #return Whether the Animator is running.
*/
public abstract boolean isRunning();
/**
* Cancels the animation. Unlike {#link #end()}, <code>cancel()</code>
* causes the animation to stop in its tracks, sending an
* {#link AnimatorListener#onAnimationCancel()} to its listeners, followed
* by an {#link AnimatorListener#onAnimationEnd()} message.
*
* <p>
* This method must be called on the thread that is running the animation.
* </p>
*/
public abstract void cancel();
/**
* Ends the animation. This causes the animation to assign the end value of
* the property being animated, then calling the
* {#link AnimatorListener#onAnimationEnd()} method on its listeners.
*
* <p>
* This method must be called on the thread that is running the animation.
* </p>
*/
public void end() {
}
/**
* This method tells the object to use appropriate information to extract
* starting values for the animation. For example, a AnimatorSet object will
* pass this call to its child objects to tell them to set up the values. A
* ObjectAnimator object will use the information it has about its target
* object and PropertyValuesHolder objects to get the start values for its
* properties. A ValueAnimator object will ignore the request since it does
* not have enough information (such as a target object) to gather these
* values.
*/
public void setupStartValues() {
}
/**
* This method tells the object to use appropriate information to extract
* ending values for the animation. For example, a AnimatorSet object will
* pass this call to its child objects to tell them to set up the values. A
* ObjectAnimator object will use the information it has about its target
* object and PropertyValuesHolder objects to get the start values for its
* properties. A ValueAnimator object will ignore the request since it does
* not have enough information (such as a target object) to gather these
* values.
*/
public void setupEndValues() {
}
/**
* Experimental feature
*/
public SupportAnimator reverse() {
if (isRunning()) {
return null;
}
RevealAnimator target = mTarget.get();
if (target != null) {
return target.startReverseAnimation();
}
return null;
}
/**
* <p>
* An animation listener receives notifications from an animation.
* Notifications indicate animation related events, such as the end or the
* repetition of the animation.
* </p>
*/
public interface AnimatorListener {
/**
* <p>
* Notifies the start of the animation.
* </p>
*/
void onAnimationStart();
/**
* <p>
* Notifies the end of the animation. This callback is not invoked for
* animations with repeat count set to INFINITE.
* </p>
*/
void onAnimationEnd();
/**
* <p>
* Notifies the cancellation of the animation. This callback is not
* invoked for animations with repeat count set to INFINITE.
* </p>
*/
void onAnimationCancel();
/**
* <p>
* Notifies the repetition of the animation.
* </p>
*/
void onAnimationRepeat();
}
/**
* <p>
* Provides default implementation for AnimatorListener.
* </p>
*/
public static abstract class SimpleAnimatorListener implements
AnimatorListener {
#Override
public void onAnimationStart() {
}
#Override
public void onAnimationEnd() {
}
#Override
public void onAnimationCancel() {
}
#Override
public void onAnimationRepeat() {
}
}
}
Its an abstract Class and extends by Animator.
and when I use this in next class
if (LOLLIPOP_PLUS) {
return new SupportAnimator(
android.view.ViewAnimationUtils.createCircularReveal(view,
centerX, centerY, startRadius, endRadius),
revealLayout);
}
ObjectAnimator reveal = ObjectAnimator.ofFloat(revealLayout,
CLIP_RADIUS, startRadius, endRadius);
reveal.addListener(new RevealAnimator.RevealFinishedIceCreamSandwich(
revealLayout, layerType));
return new SupportAnimator(reveal, revealLayout);
}
the return new SupportAnimator returns an exception of Cannot instantiate the type SupportAnimator,
its use for Circular Reveal animation and i use this in eclipse, is this suitable to work fine.