RXjava implement an observable for an object update - java

How can I add an observable to an Integer object, such that I get notified of every object update? In this case Integer number = 0; and I would like to get notified every time I add for example 1. Initially I just want to log the event. This is what I have so far, but I'm stuck.
code:
Subscriber<Integer> num = new Subscriber<Integer>() {
#Override
public void onNext(Integer num) { Log.d("RX", num.toString()); }
#Override
public void onError(Throwable e) { Log.d("RX", "error"); }
#Override
public void onCompleted() { Log.d("RX", "completed"); }
};
Observable.just(number)
/*.doOnNext(new Action1<Integer>() {
#Override
public void call(Integer integer) {
Log.d("RX", "Updated integer" + integer.toString());
}
})*/
/*.flatMap(new Func1<Integer, Observable<?>>() {
#Override
public Observable<?> call(Integer integer) {
Log.d("RX", "Updated integer" + integer.toString());
return Observable.just(number);
}
})*/
.subscribe(num);

Without knowing exactly what you are trying to achieve it's hard to give the best answer but you could implement an ObservableInteger class along the lines of the following:
public class ObservableInteger {
private Integer value;
private PublishSubject<Integer> subject = PublishSubject.create();
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
subject.onNext(value);
}
public Observable<Integer> getObservable() {
return subject.asObservable();
}
}
Then you are able to subscribe to it:
ObservableInteger obInt = new ObservableInteger();
Subscription s = obInt
.getObservable()
.subscribe(
integer -> {
// each time a new value is set
// it will be emitted here
},
Throwable::printStackTrace
);

I came across this post today and realized it is written for RxJava1. There are several changes in RxJava 2. Some of them affecting the above sample. (.subscribe returns a Disposable https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#subscription and .asObservable() is now .hide() in RxJava 2.0 https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#instance-methods)
Here is the RxJava2 compatible solution of Jahnolds answer:
public class ObservableInteger {
private Integer value;
private PublishSubject<Integer> subject = PublishSubject.create();
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
subject.onNext(value);
}
public Observable<Integer> getObservable() {
return subject.hide();
}
}
and subscribe like so:
ObservableInteger obInt = new ObservableInteger();
Disposable d = obInt
.getObservable()
.subscribe(
integer -> {
// each time a new value is set
// it will be emitted here
},
Throwable::printStackTrace
);

Related

Call a method after my class execution is complete

I made a class which it execute step by step with or without delay some functions for a amateur game which i develop. The problem is that i want to create an overriden method which is called upon finish like the exactly i give bellow:
I want to call like that:
EventQueueExecutorBuilder.of(player).after(Duration.ofSeconds(5)).apply(s -> s.setName("stackoverflow")).GET() ->
{
#Override
public void onFinish()
{
System.out.println("Execution complete!");
}
}
Basically this wait for 5 second, set the player name to "Stackoverflow" and then print out "Execution complete".
I don't know what i need to change to make overriden method like the example i gave. Here's my full code:
public class EventQueueExecutorBuilder<T> implements Runnable
{
private final T _element;
private final List<QueueExecutor> _holder = new CopyOnWriteArrayList<>();
public EventQueueExecutorBuilder(final T element)
{
_element = element;
}
public EventQueueExecutorBuilder<T> applyIf(final Predicate<T> predicate, final Consumer<T> consume)
{
if (!Util.isAnyNull(_element, predicate, consume))
{
_holder.add(new QueueExecutor(() -> Util.ifThenConsume(_element, predicate, consume), Duration.ZERO));
}
return this;
}
public EventQueueExecutorBuilder<T> apply(final Consumer<T> consume)
{
if (!Util.isAnyNull(_element, consume))
{
_holder.add(new QueueExecutor(() -> consume.accept(_element), Duration.ZERO));
}
return this;
}
public EventQueueExecutorBuilder<T> after(final Duration duration)
{
if (!Util.isAnyNull(_element, duration))
{
_holder.add(new QueueExecutor(null, duration));
}
return this;
}
public EventQueueExecutorBuilder<T> GET()
{
ThreadPoolManager.getInstance().executeEvent(this);
return this;
}
public void onFinish()
{
}
#Override
public void run()
{
if (_holder.isEmpty())
{
return;
}
final QueueExecutor executor = _holder.remove(0);
if (!executor.getDuration().isZero())
{
ThreadPoolManager.getInstance().scheduleEvent(this, executor.getDuration().toMillis());
}
else
{
executor.getTask().run();
}
}
public static <T> EventQueueExecutorBuilder<T> of(final T element)
{
return new EventQueueExecutorBuilder<>(element);
}
//#formatter:off
private static record QueueExecutor (Runnable getTask, Duration getDuration) {}
//#formatter:on
}

How to do retrofti calls with OOP?

Today i was working on my homework, which it was making simple apps with retrofit calls and learning new things for code improvement, and somehow i saw there are so many ways to write less code and do better with OOP. So to improve my code experiment I'm trying to do my retrofit calls with OOP. So this is my issue right now:
Consider a simple retrofit call with CompositeDisposable( I'm developing my simples with MVP ) :
mView.showProgress(1);
RequestRemainingProductsRequest requestRemainingProductsRequest = new RequestRemainingProductsRequest();
requestRemainingProductsRequest.distributorId = distributorId;
requestRemainingProductsRequest.requestCode = requestCode;
requestRemainingProductsRequest.requestType = 1;
NetworkCalls.getObservableList();
compositeDisposable.add(getApi().requestRemainingProducts(requestRemainingProductsRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<Products>>() {
#Override
public void accept(List<Products> products) throws Throwable {
mView.hideProgress(1);
mView.getRemainingProducts(products);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
mView.hideProgress(1);
mView.showLog(throwable.getMessage().toString());
}
}));
And, Another retrofit call without CompositeDisposable :
ProductSellerRequest productSellerRequest = new ProductSellerRequest();
productSellerRequest.centralId = centralsList.get(i).requestCentralId;
productSellerRequest.requestType = 0;
productSellerRequest.productId = Constant.currentProduct.productId;
getApi().checkProductExistInRequest(productSellerRequest)
.enqueue(new Callback<ProductSellerCallback>() {
#Override
public void onResponse(Call<ProductSellerCallback> call, Response<ProductSellerCallback> response) {
hideProgress(myViewHolder);
showAddDialog(myViewHolder, v, response, i);
}
#Override
public void onFailure(Call<ProductSellerCallback> call, Throwable t) {
hideProgress(myViewHolder);
}
});
So let's say I created a java class with NetworkCalls.java, and created 2 voids like this:
public static void getObservableList()
{
}
public static void getWithoutObservableList()
{
}
How to handle my response to return to my Presenter/Activity?
This is how i using StringBuilder and returning my String, but I'm trying do similiar way to make repository for my Network Calls, then learn all all i should know about Repository Pattern.
public static String TotalPriceStringBuilder(int Price){
String DecimalPrice = String.format("%,d", Price);
String FinalString = new StringBuilder("Price : ").append(DecimalPrice).append(" $").toString();
return String.valueOf(FinalString);
}
This is what I've tried, but i still don't know how to fix it or make it work, what to return, and how to return and etc... :
private static ApiClient mApi;
private List<Products> receivedProducts;
private int hideProgress;
private boolean status;
private String message;
public void getObservableList(RequestRemainingProductsRequest requestRemainingProductsRequest, CompositeDisposable compositeDisposable)
{
compositeDisposable.add(getApi().requestRemainingProducts(requestRemainingProductsRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<Products>>() {
#Override
public void accept(List<Products> products) throws Throwable {
hideProgress = 1;
receivedProducts = products;
status = TRUE;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
hideProgress = 1;
status = FALSE;
message = throwable.getMessage().toString();
}
}));
if (status == TRUE) {
return hideProgress, receivedProducts, status;
} else {
return hideProgress, message, status;
}
}
public ApiClient getApi() {
if (mApi == null) {
mApi = ApiService.getClient().create(ApiClient.class);
}
return mApi;
}
If i use static method I'll get bunch of errors like can't be refrenced from a static context or etc...

Java andorid RXJava2 post in service to Activity and have to times this same onNext

In service I post my event :
RxBus.getSubject().onNext(eventAddNoteAndRealize) ;
This is my RxBus :
public final class RxBus {
private static final BehaviorSubject<Object> behaviorSubject
= BehaviorSubject.create();
public synchronized static BehaviorSubject<Object> getSubject() {
return behaviorSubject;
}
}
And In my Activity I have this :
DisposableObserver<Object> disposable = RxBus.getSubject().
subscribeWith(new DisposableObserver<Object>() {
#Override
public void onNext(Object o) {
if (o instanceof EventAddNoteAndRealize) {
Toast.makeText(NewMainActivity.this , "next", Toast.LENGTH_LONG).show();
EventAddNoteAndRealize event = new EventAddNoteAndRealize(((EventAddNoteAndRealize) o).getNoteAndRealizeDAOList());
eventAddNoteAndRealize = event;
getRealizeAndNote((EventAddNoteAndRealize)o);
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
And a method onNext execute two times this same objects. I do not have idea what I did wrong
Are you sure that you are not emitting the same object 2 times because as i test your code it works good
#Override
public void run(String... args) throws Exception {
DisposableObserver<Object> disposable = RxBus.getSubject().
subscribeWith(new DisposableObserver<Object>() {
#Override
public void onNext(Object o) {
System.out.println(o);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
Observable.interval(100, TimeUnit.MILLISECONDS)
.map(aLong -> {
RxBus.getSubject().onNext(aLong);
return aLong;
}).subscribe();
}
}
final class RxBus {
private static final BehaviorSubject<Object> behaviorSubject
= BehaviorSubject.create();
public synchronized static BehaviorSubject<Object> getSubject() {
return behaviorSubject;
}
make sure that you are not emitting object to times my response is
0
1
2
3
4
5
6
.
.
.

Update events from ObjectProperty (just like in ObservableList)

I can use an extractor (Callback<E, Observable[]> extractor) to make a ListProperty fire change events if one of its elements changed one of its properties (update event).
Update Change Event in ObservableList
Is there an equivalent for ObjectProperty<>? I have an SimpleObjectProperty which I want to fire events when properties of it's value (another bean type) change (update change events).
Sample code:
public class TestBean {
public static <T extends TestBean> Callback<T, Observable[]> extractor() {
return (final T o) -> new Observable[] { o.testPropertyProperty() };
}
private final StringProperty testProperty = new SimpleStringProperty();
public final StringProperty testPropertyProperty() {
return this.testProperty;
}
public final String getTestProperty() {
return this.testPropertyProperty().get();
}
public final void setTestProperty(final String testProperty) {
this.testPropertyProperty().set(testProperty);
}
}
public class SomeType {
/**
* How can I listen for changes of TestBean#testProperty?
*/
private final ObjectProperty<TestBean> property = new SimpleObjectProperty<>();
}
I want to receive change events if the value of SomeType#property changes, but also, if SomeType#property#testProperty changes.
I cannot just listen for SomeType#property#testProperty, since I would not be notified when SomeType#property was changed (I would then listen on the wrong object for changes).
I want to receive change events if value of SomeType#property changes, but also, if SomeType#property#testProperty changes.
I cannot just listen for SomeType#property#testProperty, since I would not be notified, when SomeType#property was changed (I would then listen on the wrong object for changes).
This is a limitation of sorts of the current iteration of JavaFX. The built-in way is unreliable and you're better off using 3rd party libraries. See this answer for more information.
For you case, ReactFX can be utilized in a similar way:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.reactfx.value.Val;
import org.reactfx.value.Var;
class TestBean {
private final StringProperty testProperty = new SimpleStringProperty();
public final StringProperty testPropertyProperty() { return testProperty; }
public final String getTestProperty() { return testProperty.get(); }
public final void setTestProperty(String newTestProperty) { testProperty.set(newTestProperty); }
}
public class SomeType {
private final ObjectProperty<TestBean> property = new SimpleObjectProperty<>();
public final ObjectProperty<TestBean> propertyProperty() { return property; }
public final TestBean getProperty() { return property.get(); }
public final void setProperty(TestBean newProperty) { property.set(newProperty); }
public static void main(String[] args) {
SomeType someType = new SomeType();
Var<String> chainedTestProperty = Val.selectVar(someType.propertyProperty(), TestBean::testPropertyProperty);
chainedTestProperty.addListener((obs, oldVal, newVal) -> System.out.println(obs + " " + oldVal + "->" + newVal));
//Tests
someType.setProperty(new TestBean());
someType.getProperty().setTestProperty("s1");
TestBean bean2 = new TestBean();
bean2.setTestProperty("s2");
someType.setProperty(bean2);
someType.setProperty(new TestBean());
}
}
Output:
org.reactfx.value.FlatMappedVar#7aec35a null->s1
org.reactfx.value.FlatMappedVar#7aec35a s1->s2
org.reactfx.value.FlatMappedVar#7aec35a s2->null
The key line
Var<String> chainedTestProperty = Val.selectVar(someType.propertyProperty(), TestBean::testPropertyProperty);
is a sort of listener chaining. The first argument is a property (OvservableValue) of some type Type. The second argument is the "sub"-property of some other type Type2 inside Type, which is given as a function from Type to that property.
Now whenever any "links" in the chain change, you are notified. You can continue to listen to changes in sub-sub-... properties by continuously chaining ovservables this way.
I came up with the following:
public class ObservableValueProperty<T> extends SimpleObjectProperty<T> {
private InvalidationListener listener = null;
private final Callback<T, Observable[]> extractor;
public ObservableValueProperty() {
this(null);
}
public ObservableValueProperty(final Callback<T, Observable[]> extractor) {
this.extractor = extractor;
}
#Override
protected void fireValueChangedEvent() {
super.fireValueChangedEvent();
}
#Override
public void setValue(final T v) {
if (extractor != null) {
final T oldValue = super.get();
if (oldValue != null) {
for (final Observable o : extractor.call(oldValue)) {
o.removeListener(listener);
}
}
listener = o -> fireValueChangedEvent();
for (final Observable o : extractor.call(v)) {
o.addListener(listener);
}
}
super.setValue(v);
}
}
public class ObservableValuePropertyTest4 implements ChangeListener<Object> {
#BeforeClass
public static void setUpBeforeClass() throws Exception {
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
static class NestedBean {
StringProperty nestedProperty = new SimpleStringProperty("hans");
public static <T extends NestedBean> Callback<T, Observable[]> extractor() {
return (final T o) -> new Observable[] { o.nestedProperty };
}
#Override
public boolean equals(final Object obj) {
if (obj instanceof NestedBean) {
System.err.println(this.nestedProperty.get() + " " + ((NestedBean) obj).nestedProperty.get());
return Objects.equal(this.nestedProperty.get(), ((NestedBean) obj).nestedProperty.get());
}
return false;
}
}
private ObservableValueProperty<NestedBean> p;
private NestedBean nestedBean;
private String newNestedValue = null;
#Test
public void test01() {
p = new ObservableValueProperty<>(NestedBean.extractor());
nestedBean = new NestedBean();
p.setValue(nestedBean);
p.addListener(this);
nestedBean.nestedProperty.set("peter");
assertEquals("peter", newNestedValue);
}
#Override
public void changed(final ObservableValue<? extends Object> observable, final Object oldValue,
final Object newValue) {
System.err.println("Changed");
newNestedValue = nestedBean.nestedProperty.get();
}
}
Unfortunately, this does not fire any change events because of ExpressionHelper$SingleChange:
#Override
protected void fireValueChangedEvent() {
final T oldValue = currentValue;
currentValue = observable.getValue();
final boolean changed = (currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue);
if (changed) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}
}
This checks for equality and only if not equal, notifies all listeners. When I trigger fireValueChangedEvent() the value has already changed, and new- and old values are equal, therefore no notification to listeners.
I had the same problem last week, and after many tries, I found a solution that seems to work as expected:
I created a new class called ObjectXProperty<E>, that has the same interface of an ObjectProperty<E>;
It has constructors that can accept a Callback<E,Observable[]>, our extractor function;
Inside the ObjectXProperty, I use a SimpleObjectProperty that deleguates all methods;
The magic trick lies in the set(E value) methods : I create an ObjectBinding that simply send back the value, but it uses the extractor function to decide when it's become invalidated!
This trick will not be applied if the bind method was used previously on the ObjectXProperty, to let the "real" binding do his job; it will work again if the unbind method is called;
Here's my new class ObjectXProperty<E> :
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.util.Callback;
/**
*
* #author Claude Bouchard - 2017
*/
public class ObjectXProperty<E> extends ObjectProperty<E> {
SimpleObjectProperty<E> p;
Callback<E, Observable[]> extractor;
boolean externalBound = false;
public ObjectXProperty(Callback<E, Observable[]> extractor) {
this.extractor = extractor;
}
public ObjectXProperty(E init, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty();
this.extractor = extractor;
set(init);
}
public ObjectXProperty(Object bean, String name, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty(bean, name);
this.extractor = extractor;
}
public ObjectXProperty(Object bean, String name, E init, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty(bean, name);
this.extractor = extractor;
set(init);
}
#Override
public void set(E value) {
if (!externalBound) {
if (value != null) {
p.bind(Bindings.createObjectBinding(() -> {
return value;
}, extractor.call(value)));
} else {
p.bind(Bindings.createObjectBinding(() -> {
return value;
}, new Observable[]{}));
}
} else {
p.set(value); //As expected, it will throw a java.lang.RuntimeException
}
}
#Override
public E get() {
return p.get();
}
#Override
public void addListener(ChangeListener<? super E> listener) {
p.addListener(listener);
}
#Override
public void removeListener(ChangeListener<? super E> listener) {
p.removeListener(listener);
}
#Override
public void addListener(InvalidationListener listener) {
p.addListener(listener);
}
#Override
public void removeListener(InvalidationListener listener) {
p.removeListener(listener);
}
#Override
public Object getBean() {
return p.getBean();
}
#Override
public String getName() {
return p.getName();
}
#Override
public void bind(ObservableValue<? extends E> observable) {
p.bind(observable);
externalBound = true;
}
#Override
public void unbind() {
p.unbind();
externalBound = false;
set(get()); //to reactivate the extractor on the last value
}
#Override
public boolean isBound() {
return externalBound;
}
}
I think you need to add a listener to your object. This can be done simply. First of all you should write your class with a constructor and with getters this way:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
public class SomeType {
public ObjectProperty<TestProperty> property;
public SomeType(TestProperty testProperty) {
this.property = new SimpleObjectProperty<>(testProperty);
}
public TestProperty getProperty() {
return property.get();
}
public ObjectProperty<TestProperty> propertyProperty() {
return property;
}
}
Then anywhere you have an instance of SomeType you can chain the properties, so you get the property the property's testProperty() and then simply add a listener to it.
someType.getProperty().testProperty().addListener((observable, oldValue, newValue) -> {
// Do whatever you want if the its value changed.
// You can also use its old or new value.
});

RxJava, get first item if exists

I'm trying to get the first item from a list using RxJava. However, I don't want it to throw an error if the item doesn't exist. Instead I want to be able to handle that myself by providing a default item.
The code I created below works correctly in retrieving the first item in a list. Though I can't figure out how to incorporate .exists() into it.
api.getLibraryEntries(username)
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<List<Entry>, Observable<Entry>>() {
#Override
public Observable<Entry> call(List<Entry> Entries) {
return Observable.from(Entries);
}
})
.first(new Func1<Entry, Boolean>() {
#Override
public Boolean call(Entry entry) {
return entry.getId() == id;
}
})
.subscribe(
new Action1<Entry>() {
#Override
public void call(Entry entry) {
view.showEntry(entry);
}
},
new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
view.showError(throwable.getMessage());
}
});
Any help is appreciated.
There is a firstOrDefault operator:
// ...
.firstOrDefault(yourDefaultValue, new Func1<Entry, Boolean>() {
#Override
public Boolean call(Entry entry) {
return entry.getId() == id;
}
})
// ...

Categories

Resources