New to RxJava and I have question about interface callbacks ( called from inner layer/module of code through interface variable) vs RxJava.
To make it more clear, quick example:
Standard callback interface implementation, interface, class A and B
interface CustomCallback {
void onCallbackCalled(String str);
}
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB(new CustomCallback() {
#Override
public void onCallbackCalled(String str) {
System.out.println("Callback called " + str);
}
});
}
}
class ClassB {
private CustomCallback customCallback;
public ClassB(CustomCallback callback) {
customCallback = callback;
}
private void somethingHappened() {
customCallback.onCallbackCalled("method somethingHappened");
}
}
When classB method "somethingHappened" is called, result is: "Callback called method somethingHappened".
Interface's method onCallbackCalled(String str) can be called from classB as many times as I want.
CLASS A ↓ ............................................ injection of interface through constructor
CLASS B................↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ onCallbackCalled(...) 0...n number
Now RxJava. 99% of cases which I find.
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private Observable<String> getObservable() {
return Observable.just(can be different from "just", for sake of example);
}
}
Scheme is:
CLASS A ↓........................ one call for getting Observable resource
CLASS B................↑ EDIT returns observable which emits 0...n values
So basically you call from top layer ( in this example) and you get response about state from inner layer.
QUESTIONS:
1) What in case when you have a model ( inner layer) which is changing dynamically ( but not any kind of AsyncTask etc.), and you want to notify top layer ( UI for example) that state has changed ( good example: game).
2) Is there any kind of "bridge" class in RxJava library ( I think about it as "subscribe to it, then you can pass arguments to it as many times as you want and information/observable will be emitted to subscribers).
3) Is there any sense and advanatage of trying to do that instead of standard interface callbacks ( in case like above, not " click button, get response once")
UPDATE, ANSWER BASED ON EXAMPLE ABOVE
As Bob Dalgleish mentioned, way of making such bridge is by using one of the class extending Subject<T> rxjava.
http://reactivex.io/documentation/subject.html
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getCallbackSubjectRx()
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private BehaviorSubject<String> mCallbackRx;
public ClassB() {
mCallbackRx = BehaviorSubject.create();
}
// method somethingHappened can be invoked whenever whe want and
// it will send given parameter to all subscribers
private void somethingHappened() {
mCallbackRx.onNext("method somethingHappened");
}
// multiple subscribers allowed
public BehaviorSubject<String> getCallbackSubjectRx() {
return mCallbackRx;
}
}
Downside might be, that if we want to use one "bridge" to handle multiple callback types ( interface have methods, we use only one method: "onNext()"), we might need to create wrapper class with callback parameters. Which isn't big problem in my opinion.
On the other hand, we get access to all of RxJava operators.
http://reactivex.io/documentation/operators.html
( Example above is for RxJava2, where Disposable is basically Subscription from RxJava1).
The first thing to note is that
CLASS B................↑ returns 0...n observables to observer
is not true. Class B returns an observable, on which it will occasionally emit 0..n values.
(the question is not clear). The inner observable, from class B, is changing state for whatever reason. The most common reason is that another process/task/thread is feeding it, and you want to display the resulting state in the UI.
A simple type of "bridging" class that I use all the time any of the several Subject<> classes. You can emit new values to them using .onNext() and the subscribers will get those values.
If callback interfaces were all standardized, then they would have some advantage, but they vary all over the place. You have to remember that you need some particular interface for this thing you are looking at and and a different one for the other thing. While UI events tend to be quite uniform these days, trying to mix UI events and network events and database events will still leave you feeling overwhelmed. Having a much smaller class of interfaces, mostly encapsulated inside of the rxJava generic classes, makes composing functionality much easier.
Edit: Improve example code.
There is a good article from Yammer Engineering on using Observable.create() (formerly Observable.fromEmitter(), formerly Observable.fromAsync(). The important points he makes are
Using Observable.create() handles the subscription step for you by registering a listener to the underlying interface. More importantly, it arranges to de-register the listener when the unsubscribe() occurs.
Out of the box, this code handles multiple subscribers, each of which receives its own observable stream of data.
As I mentioned above, the listener protocol is particular to the thing you register with. If that thing supports only a single listener, then you will likely want to introduce a Subject that subscribes to the thing under observation, and all your other observers subscribe to the subject.
End of edit.
My favorite example of composition of solutions is the distinctUntilChanged() operator. Because it is an operator that works on a generic observable, it encapsulates the stateful property of saving consecutive values for comparison and only emitting differing ones. I use it frequently for logging state changes. To achieve the same end using standard callback interfaces would require adding a different interface for saving prior values to every existing interface.
So, yes, most of the time it is worth using the rxJava approach of observables, simply for the sake of not having to remember which of the many call back protocols might be applicable in the current case.
Related
I have a MVVM architecture in my Android app. In an activity, I invoke a method to try to create something from service/repository and return it. I am using RxJava.
Here is the flow:
I click something in view, it invokes method in the Activity.
Method in Activity invokes method in ViewModel.
Method in ViewModel invokes method in Interactor(/use-case).
Interactor has access to service and tries to create something from that service.
Here is the code for this:
Activity:
#Override
public void onCreateWalletClick(String password) {
addWalletViewModel.createWallet(password);
}
ViewModel:
public class AddWalletViewModel extends BaseViewModel {
private AddWalletInteractor addWalletInteractor;
private final MutableLiveData<Wallet> newWallet = new MutableLiveData<Wallet>();
private final MutableLiveData<ErrorCarrier> newWalletError = new MutableLiveData<ErrorCarrier>();
public LiveData<Wallet> newWallet() {
return newWallet;
}
public AddWalletViewModel(AddWalletInteractor addWalletInteractor) {
this.addWalletInteractor = addWalletInteractor;
}
public Single<Wallet> createWallet(String password){
return addWalletInteractor.addWallet(password)
.subscribe(wallet -> newWallet.postValue(wallet), this::addErrorToLiveData);
}
private void addErrorToLiveData(Throwable throwable){
newWalletError.postValue(new ErrorCarrier());
}
}
Interactor:
public class AddWalletInteractor {
private final KeyStoreServiceInterface keyStoreServiceInterface;
public AddWalletInteractor(KeyStoreServiceInterface keyStoreServiceInterface) {
this.keyStoreServiceInterface = keyStoreServiceInterface;
}
public Single<Wallet> addWallet(String password){
return keyStoreServiceInterface.
createWalletAndReturnWallet(password);
}
}
Service:
#Override
public Single<Wallet[]> getAllWallets() {
return Single.fromCallable(()-> {
Accounts accounts = keyStore.getAccounts();
int amount = (int) accounts.size();
Wallet[] wallets = new Wallet[amount];
for (int i = 0; i<amount; i++){
org.ethereum.geth.Account gethAccount = accounts.get(i);
wallets[i] = new Wallet(gethAccount.getAddress().getHex().toLowerCase());
}
return wallets;
}).subscribeOn(Schedulers.io());
}
Problem is I can not manage to get this to work by tweaking the code. Right now it forces me to cast to (Single) in the return of the createWallet() method in the viewmodel. When running the app, it crashes in that method with:
java.lang.ClassCastException:
io.reactivex.internal.observers.ConsumerSingleObserver cannot be cast
to io.reactivex.Single
at addwallet.AddWalletViewModel.createWallet(AddWalletViewModel.java:31)
Please keep in mind I am new to RxJava, I am still trying to figure it out. Any suggestions here?
The cast performed in the createWallet method will always fail.
Solution 1
The simplest way to fix the crash is to change the return type of that method to io.reactivex.disposables.Disposable, assuming you're using RxJava 2. If you're using RxJava 1, then have it return rx.Subscription. The code you presented that calls the createWallet method doesn't seem to use the returned value so it shouldn't make a difference.
Solution 2
If you really do need the return type to be Single and you want to keep the same behavior, then an alternate solution would be to change the createWallet method as follows:
public Single<Wallet> createWallet(String password) {
return addWalletInteractor.addWallet(password)
.doOnSuccess(wallet -> newWallet.postValue(wallet))
.doOnError(this::addErrorToLiveData);
}
The method now returns a new Single that does whatever the Single returned from addWallet does and additionally invokes the appropriate lambda function when a value is successfully emitted or an error occurs. You would also need to modify the call site for the method as follows:
#Override
public void onCreateWalletClick(String password) {
addWalletViewModel.createWallet(password).subscribe();
}
That subscribe call is needed to have the Single start emitting values. It takes no parameters because you already do all of the interesting work in the createWallet method itself. Both snippets were written with RxJava 2 in mind, but I believe they will also work in RxJava 1 as is.
If you haven't already done so, you should check out the official Rx website as it provides a ton of information on how reactive streams work and how to use them.
Since you're new to RxJava and the documentation is so vast, here's a brief overview of the subscription concept and how it applies to your situation.
RxJava and other stream-based libraries like it have two main components: producers and consumers. Producers supply values and consumers do something with those supplied values.
Single is a kind of producer that only produces one value before terminating. In your case, it produces a reference to the newly created wallet. In order to do something with that reference, it needs to be consumed. That's what the subscribe method on the Single class does. When the Single returned by the addWallet method produces a value, the lambda passed to the subscribe method is invoked and the wallet parameter in that lambda is set to the produced value.
The return type of the subscribe method is NOT itself a Single. When a consumer and a producer are coupled together by the subscribe method, it forms a connection which is represented by the Disposable class. An instance of that class has methods to cancel the connection before the producer is done producing values or to check if the connection has been cancelled. It is this connection object that is returned by the subscribe method.
Note that until this connection is made via one of the subscribe overloads, the producer will not start producing items. I.e., a Single that is never subscribed to will never do anything. It's analogous to a Runnable whose run method is never called.
Background:
Nothing special, I'm using Java for Android.
Problem:
I want to allow my users to create multiple instances of an object and register a callback Interface into each instance (think of an error callback).
The object has several children/sub-children/etc... Each child can return this event.
I expect 1-10 instances in entire lifetime of app.
I'm trying to avoid using a singleton/static events listener.
Possible solutions (and reasons not to use them):
1) Register a BroadcastReceiver in each parent-object instance and allow each grand child notify the event on Intent level. This should allow the main object to notify my user about the event.
The problem is the multiple instances would require multiple BroadcastReceivers which I expect to be heavy or just less than optimal.
2) Register one BroadcastReceiver and find a way to let it decide which instance of the object should be notified of an event, and actually send it to it. The problem is that I'm not sure how to notify the objects themselves.
3) Let the callback interface pass as an argument from parent to each of the children/grandchilren/etc... But this would be messy.
4) Use something like EventBus library (which I understand would be the same thing as BroadcastReceiver, only Reflection based, thus slower).
5) Anything else?
I don't know if this is the best solution for you but I think it would work if I understand your requirements correctly.
public class Listener extends Observable implements Observer {
private List<Observer> clients = new ArrayList<>();
public void addClient(Observer client){
clients.add(client);
}
#Override
public void update(Observable o, Object arg) {
for(Observer client : clients){
client.update(o, arg); // Or whatever you need to do
}
}
public class DataSource extends Observable {
private Observer observer;
public DataSource(Observer o){
observer = o;
}
// Notify observer of changes at appropriate time
}
public class Consumer implements Observer {
public Consumer(){
Listener listener = ...;
listener.addClient(this);
}
#Override
public void update(Observable o, Object arg) {
// Handle appropriately
}
}
}
DataSource is your "sub-objects", Consumer is the end client of the events, and Listener is the class in the middle. I don't know why the clients can't directly register for events with the "sub-objects" but that is what you said! This is modeled as inner classes here for simplicity but I assume you would not do that.
I used to work with EventBus before, which was easy to use and easy to understand. This time, however, I would like to try out RxJava for event bus-like communication, however it is not very clear how to remove events from RxJava or, better to say, how it should be designed properly to have similar behavior as EventBus has when I call removeStickyEvent?
In RxJava I can use BehaviorSubject to reply last even when I subscribe to this observable, but what should I do when this event is handled? What if I do not want to have this event replayed again?
For instance, one fragment fires an event and then finishes. Another fragment listens to this event and handles it. Then, if this app fires that "another" activity again from different circumstances, then it will subscribe to the same BehaviorSubject again and will handle that stale event again, which is not what I would like to achieve.
I used this project as a reference https://github.com/marwinxxii/AndroidRxSamples/blob/master/app/src/main/java/com/github/marwinxxii/rxsamples/EventBusSampleActivity.java
As long as you do not plan to allow your events to be null, I think that can be achieved pretty easily.
Exactly as you said, you could use BehaviorSubject to propagate sticky events, and when you want to removeStickyEvent from the bus, you can just emit a null object (to "flush" the subject).
Something like this (from the top of my head - not tested, without generics, just a simple Object-event based example):
public class RxEventBus {
PublishSubject<Object> eventsSubject = PublishSubject.create();
BehaviorSubject<Object> stickyEventsSubject = BehaviorSubject.create();
public RxEventBus() {
}
public Observable<Object> asObservable() {
return eventsSubject;
}
public Observable<Object> asStickyObservable() {
return stickyEventsSubject.filter(new Func1<Object, Boolean>() {
#Override
public Boolean call(Object o) {
return o != null;
}
});
}
public void postEvent(#NonNull Object event) {
eventsSubject.onNext(event);
}
public void postStickyEvent(#NonNull Object stickyEvent) {
stickyEventsSubject.onNext(stickyEvent);
}
public void removeStickyEvent(){
stickyEventsSubject.onNext(null);
}
}
I just switched over from iPhone to Android and am looking for something similar to where in the iPhone SDK, when a class finishes a certain task, it calls delegate methods in objects set as it's delegates.
I don't need too many details. I went through the docs and didn't find anything (the closest I got was "broadcast intents" which seem more like iOS notifications).
Even if someone can point me to the correct documentation, it would be great.
Thanks!
Never mind... found the answer here :)
http://www.javaworld.com/javaworld/javatips/jw-javatip10.html
Pasting from the article so as to preserve it:
Developers conversant in the event-driven programming model of MS-Windows and the X Window System are accustomed to passing function pointers that are invoked (that is, "called back") when something happens. Java's object-oriented model does not currently support method pointers, and thus seems to preclude using this comfortable mechanism. But all is not lost!
Java's support of interfaces provides a mechanism by which we can get the equivalent of callbacks. The trick is to define a simple interface that declares the method we wish to be invoked.
For example, suppose we want to be notified when an event happens. We can define an interface:
public interface InterestingEvent
{
// This is just a regular method so it can return something or
// take arguments if you like.
public void interestingEvent ();
}
This gives us a grip on any objects of classes that implement the interface. So, we need not concern ourselves with any other extraneous type information. This is much nicer than hacking trampoline C functions that use the data field of widgets to hold an object pointer when using C++ code with Motif.
The class that will signal the event needs to expect objects that implement the InterestingEvent interface and then invoke the interestingEvent() method as appropriate.
public class EventNotifier
{
private InterestingEvent ie;
private boolean somethingHappened;
public EventNotifier (InterestingEvent event)
{
// Save the event object for later use.
ie = event;
// Nothing to report yet.
somethingHappened = false;
}
//...
public void doWork ()
{
// Check the predicate, which is set elsewhere.
if (somethingHappened)
{
// Signal the even by invoking the interface's method.
ie.interestingEvent ();
}
//...
}
// ...
}
In that example, I used the somethingHappened predicate to track whether or not the event should be triggered. In many instances, the very fact that the method was called is enough to warrant signaling the interestingEvent().
The code that wishes to receive the event notification must implement the InterestingEvent interface and just pass a reference to itself to the event notifier.
public class CallMe implements InterestingEvent
{
private EventNotifier en;
public CallMe ()
{
// Create the event notifier and pass ourself to it.
en = new EventNotifier (this);
}
// Define the actual handler for the event.
public void interestingEvent ()
{
// Wow! Something really interesting must have occurred!
// Do something...
}
//...
}
That's all there is to it. I hope use this simple Java idiom will make your transition to Java a bit less jittery.
The pendant for kotlin.
Define your interface: In my example I scan a credit card with an external library.
interface ScanIOInterface {
fun onScannedCreditCard(creditCard: CreditCard)
}
Create a class where you can register your Activity / Fragment.
class ScanIOScanner {
var scannerInterface: ScanIOInterface? = null
fun startScanningCreditCard() {
val creditCard = Library.whichScanCreditCard() //returns CreditCard model
scannerInterface?.onScannedCreditCard(creditCard)
}
}
Implement the interface in your Activity / Fragment.
class YourClassActivity extends AppCompatActivity, ScanIOInterface {
//called when credit card was scanned
override fun onScannedCreditCard(creditCard: CreditCard) {
//do stuff with the credit card information
}
//call scanIOScanner to register your interface
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val scanIOScanner = ScanIOScanner()
scanIOScanner.scannerInterface = this
}
}
CreditCard is a model and could be define however you like. In my case it includes brand, digits, expiry date ...
After that you can call scanIOScanner.startScanningCreditCard() wherever you like.
The main content of this video tutorial is to show how to use interfaces to delegate methods / data exchange between different Fragments and activities, but it is great example to learn how delegate pattern can be implemented in Java for Android.
Java callback is not the same thing like ios delegate, in ios you can use a callback almost the same way like in Android. In Android there is startActivityForResult that can help you to implement the tasks for what ios delegate is used.
I believe ListAdapter is a example of delegation pattern in Android.
Kotlin's official Delegation pattern:
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main() {
val b = BaseImpl(10)
Derived(b).print()
}
See: https://kotlinlang.org/docs/delegation.html
In Android application development, I frequently go through the word CallBack in many places. I want to know what it means to tell us technically - and how I can manage to use the callback in applications. I need a guide to understand it and use it.
i want to know what it means, tell
us technically
http://en.wikipedia.org/wiki/Callback_%28computer_science%29
"In object-oriented programming languages without function-valued arguments, such as Java, [callbacks] can be simulated by passing an abstract class or interface, of which the receiver will call one or more methods, while the calling end provides a concrete implementation. Such objects are effectively a bundle of callbacks, plus the data they need to manipulate. They are useful in implementing various design patterns such as Visitor, Observer, and Strategy."
how i can manage the callback of the
applications
I have no idea what this means.
Hmm. How about an example. You write a quicksort algorithm in C. The user who wants to use your algorithm must supply a compare method appropriate for what the user is sorting with your algorithm. The user must pass a function pointer to the user's compare method to your quicksort code. The quicksort code uses this address, the function pointer, to CALL BACK to the user's compare function. You provide a function prototype, no implementation, since you cannot possibly know how to determine the ordinality of what is being sorted. The user supplies the implementation of compare that makes sense for what the user is sorting. This implementation must match the function prototype. The function pointer is used by the quicksort alogorithm to reach back and touch the user's code.
This is actually about polymorphism.
In java, you can use an interface to do this. So for sorting, see the interface IComparer and IComparable.
A Callable interface can be used to run a piece of code as Runnable does. However, Callable can return the result and can throw checked an exception.
For more detail.
http://developer.android.com/reference/java/util/concurrent/Callable.html
By using Callable interfaces you can pass an argument as function I added a simple code snippet for understanding.
public class MainActivity<V> extends Activity {
Callable<String> doLogin=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
doLogin=new Callable<String>() { //created but not called now.
#Override
public String call() throws Exception {
//make some piece of code
return "something"; //or false
}
};
CheckSession checkSession=new CheckSession("sessionName");
String sessionKey="";
try { //we are sending callable to the DAO or any class we want
sessionKey=checkSession.getSessionKey(doLogin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class CheckSession{
String sessionName="";
Callable<String> func=null;
public CheckSession(String sessionName) {
super();
this.sessionName = sessionName;
}
public String getSessionKey(Callable<String> doLogin) throws Exception{
func=doLogin;
return (String) func.call();
}
}