I am using #MrEngineer13's SnackBar implementation and was wondering how to capture 2 separate "ActionClick" events - depending on when the actionclick event occurs, I need to do different things.
The builder looks like this -
new SnackBar.Builder(this)
.withOnClickListener(this)
.withMessage("This library is awesome!") // OR
.withMessageId(messageId)
.withTypeFace(myAwesomeTypeFace)
.withActionMessage("Action") // OR
.withActionMessageId(actionMsgId)
.withTextColorId(textColorId)
.withBackGroundColorId(bgColorId)
.withVisibilityChangeListener(this)
.withStyle(style)
.withDuration(duration)
.show();`
and the onMessageClick takes a "token" parameter -
#Override
public void onMessageClick(Parcelable token) {
}
What I am not able to figure out is, how to pass this "token" when the click happens.
depending on when the actionclick event occurs, I need to do different things
Handle that in the body of onMessageClick():
#Override
public void onMessageClick(Parcelable token) {
if (shouldIDoX()) {
doX();
}
else {
doY();
}
}
(where you supply relevant implementations of shouldIDoX(), doX(), and doY().
What I am not able to figure out is, how to pass this "token" when the click happens
There is a withToken() method on the Builder that you can use to supply the Parcelable to be passed into onMessageClick(). That being said, the JavaDocs describe it as "The token used to restore the SnackBar state", which would make me a bit nervous about messing with it.
Related
I have an issue with my network client design. I have a use case, when the client tries to request an item from a REST API, but in case the API returns a 404 HTTP status code I need to send a request to create the item on the server and then request the item again.
I would like to use RxJava to avoid the callback hell. Is this a valid use case RxJava? Is it possible to create such a conditional sub-request?
Thank you for your time and answers.
Based on your question, I assume you have something that look like
public Observable<Item> getItem();
that will either return the item, or fire an error and
public Observable<?> createItem();
That will create one.
You can use those two together like so:
public Observable<Item> getOrCreateItem() {
return getItem().onErrorResumeNext(error -> {
// Depending on your framework, figure out which is the result code
if (error.getResultCode() == 404) {
return createItem().flatMap(ignored -> getItem());
} else {
return Observable.error(error);
}
});
}
With Retrofit, you'd have to simply make sure the exception is a RetrofitError, cast it, and get the response and the status code. (((RetrofitError) error).getResponse().getStatus())
Where is the documentation/sample for all overloads of invokeApi function for Azure Mobile Service client SDK for Android?
I found this article and tried following code, which does not work. There are no compile time or run time errors, invokeApi gets called, but it does not come back to onSuccess or onFailure. If I call invokeApi without order object, everything works as expected
PizzaOrder order = new PizzaOrder();
order.Size = "Large";
order.Flavor = "Four cheeses";
order.UserPhone = "555-555-1234";
ListenableFuture<PizzaOrderResponse> testresult = mClient.invokeApi("bookservice", order, PizzaOrderResponse.class);
Futures.addCallback(testresult, new FutureCallback<PizzaOrderResponse>() {
#Override
public void onFailure(Throwable exc) {
// failure handling code here
}
#Override
public void onSuccess(PizzaOrderResponse testresult) {
// success handling code here
}
});
One of the properties in the data object being returned by the custom API had incorrect data type. I am still not sure where the good documentation is and why custom API call did not fail but at least it is working now.
I'm playing around with RXJava, retrofit in Android. I'm trying to accomplish the following:
I need to poll periodically a call that give me a Observable> (From here I could did it)
Once I get this list I want to iterate in each Delivery and call another methods that will give me the ETA (so just more info) I want to attach this new info into the delivery and give back the full list with the extra information attached to each item.
I know how to do that without rxjava once I get the list, but I would like to practice.
This is my code so far:
pollDeliveries = Observable.interval(POLLING_INTERVAL, TimeUnit.SECONDS, Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
.map(tick -> RestClient.getInstance().getApiService().getDeliveries())
.doOnError(err -> Log.e("MPB", "Error retrieving messages" + err))
.retry()
.subscribe(deliveries -> {
MainApp.getEventBus().postSticky(deliveries);
});
This is giving me a list of deliveries. Now I would like to accomplish the second part.
Hope I been enough clear.
Thanks
Finally I found a nice way to do it.
private void startPolling() {
pollDeliveries = Observable.interval(POLLING_INTERVAL, TimeUnit.SECONDS, Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
.flatMap(tick -> getDeliveriesObs())
.doOnError(err -> Log.e("MPB", "Error retrieving messages" + err))
.retry()
.subscribe(this::parseDeliveries, Throwable::printStackTrace);
}
private Observable<List<Delivery>> getDeliveriesObs() {
return RestClient.getInstance().getApiService().getDeliveries()
.flatMap(Observable::from)
.flatMap(this::getETAForDelivery)
.toSortedList((d1, d2) -> {
if (d1.getEta() == null) {
return -1;
}
if (d2.getEta() == null) {
return 1;
}
return d1.getEta().getDuration().getValue() > d2.getEta().getDuration().getValue() ? 1 : -1;
});
}
Let's go step by step.
First we create an Observable that triggers every POLLING_INTERVAL time the method getDeliveriesObs() that will return the final list
We use retrofit to get an Observable of the call
We use flatMap to flattern the resut list and get in the next flatmap a Delivery item, one by one.
Then we get the estimated time of arrival set inside the Delivery object and return it
We sort the list to order by estimated time of arrival.
In case of error we print and retry so the interval does not stop
We subscribe finally to get the list sorted and with ETA inside, then we just return it or whatever you need to do with it.
It's working properly and it's quite nice, I'm starting to like rxjava :)
I haven't spent a lot of time with Java 8 lambdas, but here's an example of mapping each object to a different object, then getting a List<...> out at the other end in plain ol' Java 7:
List<Delivery> deliveries = ...;
Observable.from(deliveries).flatMap(new Func1<Delivery, Observable<ETA>>() {
#Override
public Observable<ETA> call(Delivery delivery) {
// Convert delivery to ETA...
return someEta;
}
})
.toList().subscribe(new Action1<List<ETA>>() {
#Override
public void call(List<ETA> etas) {
}
});
Of course, it'd be nice to take the Retrofit response (presumably an Observable<List<Delivery>>?) and just observe each of those. For that we ideally use something like flatten(), which doesn't appear to be coming to RxJava anytime soon.
To do that, you can instead do something like this (much nicer with lambdas). You'd replace Observable.from(deliveries) in the above example with the following:
apiService.getDeliveries().flatMap(new Func1<List<Delivery>, Observable<Delivery>>() {
#Override
public Observable<Delivery> call(List<Delivery> deliveries) {
return Observable.from(deliveries);
}
}).flatMap(...)
I need to implement quite popular template of app behaviour - give opportunity to user to retry failed requests. Right now I catch failed request with SpiceServiceListener, and shows dialog where user can press "Retry" button. Unfortunately, using the same CachedSpiceRequest object with SpiceManager.execute() don't give desired behaviour, because RS removing all request listeners from mapRequestToLaunchToRequestListener if request wasn't successful. So request can work fine, but it will not return any information to my Activity.
Is there easy way (without modifying code of library) to implement this?
Unfortunately looks like there are no abstract solution for situation like this, so I had to add code like this in every request.
getSpiceManager().execute(r, new RequestListener<CountProfiles>() {
#Override
public void onRequestFailure(SpiceException spiceException) {
if (act.getSupportFragmentManager().findFragmentByTag("network_problem") == null) {
NetworkProblemDialogFragm.newInstance(r, this).show(act.getSupportFragmentManager(), "network_problem");
} else {
((NetworkProblemDialogFragm) act.getSupportFragmentManager().findFragmentByTag("network_problem")).setSpiceRequest(r);
((NetworkProblemDialogFragm) act.getSupportFragmentManager().findFragmentByTag("network_problem")).setRequestListener(this);
}
}
#Override
public void onRequestSuccess(CountProfiles countProfiles) {
}
});
NetworkProblemDialogFragm is a DialogFragment with Retry button, on click on this button I re execute failed request, using given RequestListener.
Not very beautiful solution, but looks like there no better one.
I'm trying to use rx-java on Android to do few sequential http requests, each of which is dependent of the response of the former one.
This does not quite fit the map() / doFinall() model and so I'm not sure what would be the best way to do this without getting into "callback hell" as well as writing concise code.
More concretely:
do http GET "/x"
do http GET "/y" if (2) was successfully
do calculation on the result of GET /y
Any suggestions on how to go about this?
I think flatMap is what you're looking for. For example, assuming you have the following methods:
Observable<Foo> getFoo();
Observable<Bar> getBar(Foo foo); //needs a Foo first
You could effectively chain them this way:
getFoo().flatMap(new Func1<Foo, Observable<Bar>>() {
#Override
public Observable<Bar> call(Foo foo) {
return getBar(foo);
}
});
You could then perform some calculation with the final result Bar by subscribing to the resulting Observable<Bar> (full example shown for clarity):
getFoo().flatMap(new Func1<Foo, Observable<Bar>>() {
#Override
public Observable<Bar> call(Foo foo) {
return getBar(foo);
}
}).subscribe(new Action1<Bar>() {
#Override
public void call(Bar bar) {
//everything succeeded, so perform calculation to the Bar
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
//handle an error that occurred anywhere in the chain
}
});
Note that an error anywhere in the process of getting the Foo or the Bar will be handled by the Action1 that we provide when subscribing to the Observable. It is, of course, painfully verbose because Java, but at least it avoids nesting Observables/callback hell.