Friday, 25 July 2014

RxJava for UI events on Android example

In the paper Deprecating the Observer Pattern, part 3 "Reactors: composable observers without inversion of control" there is an example of the reactor that processes mouse input events, written in Scala using scala-react library. In this post I'll describe how to create composable observers for touch events for Android with RxJava library.

The tools used are the RxJava library itself and retrolambda plugin to employ lambda functions on Android. Here is the sample build.gradle file with these two dependencies. To bridge from Android event listeners to RxJava Observers the Subject is created, it will listen to touch events and reemit them to RxJava Observers.
private final PublishSubject mTouchSubject = PublishSubject.create();
 
public MouseDragView(Context context, AttributeSet attr) {
        super(context, attr);
        
        setOnTouchListener((View v, MotionEvent event) -> {
            mTouchSubject.onNext(event);
                return true;
        });
}


Then the Observables are created by filtering the Subject Observable and each of them exposes corresponding event stream to touch ups, moves and touch downs. While each of these three new observables will receive all the events from the Subject Observable, they will call their subcribers' onNext() function only for the events that suit the filter predicate.

private final Observable mTouches = mTouchSubject.asObservable();
    private final Observable mDownObservable = 
               mTouches.filter(ev -> ev.getActionMasked() == MotionEvent.ACTION_DOWN);
    private final Observable mUpObservable =
               mTouches.filter(ev -> ev.getActionMasked() == MotionEvent.ACTION_UP);
    private final Observable mMovesObservable =
               mTouches.filter(ev -> ev.getActionMasked() == MotionEvent.ACTION_MOVE);


Path should be created with the touch down event. So the new Observer is spawned using the subcribe (final Action1 onNext) function of Observable. The lambda function that is passed as an argument will be the newly created Observer's onNext() handler.

    mDownObservable.subscribe(downEvent -> {
           final Path path = new Path();
           path.moveTo(downEvent.getX(), downEvent.getY());
           Log.i(downEvent.toString(), "Touch down");
    });


After the path is created and has the starting point, lets watch for the move events.

 mDownObservable.subscribe(downEvent -> {
            final Path path = new Path();
            path.moveTo(downEvent.getX(), downEvent.getY());
            Log.i(downEvent.toString(), "Touch down");

            mMovesObservable
                    .subscribe(motionEvent -> {
                        path.lineTo(motionEvent.getX(), motionEvent.getY());
                        draw(path);
                        Log.i(motionEvent.toString(), "Touch move");
            });
        });


For each touch down event the new Observer for move events is created. Now we need to also create an Observer for touch up event. On touch up we'll unsubscribe from move events, and close the path. It's important to unsubscribe because otherwise for each next touch down we will be creating yet another moves Observer while leaving behind all the moves Observers created for previous touch downs. The unsubscription is achieved via takeUntil() operator. The RxJava wiki states that takeUntil() "emits the items from the source Observable until another Observable emits an item or issues a notification. This means that our Observer will be automatically unsubscribed from moves Observable when touch up Observable emits an item. Hence the moves Observable will become "cold" Observable, as it doesn't have Observers, and will stop emitting the items.

    mDownObservable.subscribe(downEvent -> {
            final Path path = new Path();
            path.moveTo(downEvent.getX(), downEvent.getY());
            Log.i(downEvent.toString(), "Touch down");

            mMovesObservable
                     .takeUntil(mUpObservable
                             .doOnNext(upEvent -> {
                                 draw(path);
                                 path.close();
                                 Log.i(upEvent.toString(), "Touch up");
                             }))
                    .subscribe(motionEvent -> {
                        path.lineTo(motionEvent.getX(), motionEvent.getY());
                        draw(path);
                        Log.i(motionEvent.toString(), "Touch move");
                    });

        });


The full example project for Android Studio is at github



23 comments :

  1. It is really a great work and the way in which u r sharing the knowledge is excellent.
    Thanks for helping me to understand basic concepts. As a beginner in android programming your post help me a lot.Thanks for your informative article. Android Training in velachery | Android Training institute in chennai

    ReplyDelete
  2. Given so much info in it, These type of articles keeps the users interest in the website, and keep on sharing more ... good luck.
    Android Training in chennai | Android Training

    ReplyDelete
  3. Thanks for Sharing your knowledge and information, it is very nice and more informative, Thanks.
    Dot Net Training in chennai | Dot Net Training in velachery

    ReplyDelete
  4. What a nice article!

    I'd like to know if I can implement this example (with a few improvements) in an app I am working on. Basically it is an app which I expect to wrap 100+ examples of RxJava, including many operators, hot observables, backpressure, etc. I will publish it on GitHub.

    You can check my blog (androidahead.com) which I have already published some articles about RxJava. Basically this new app will include all examples already published plus some others I found useful (including this one).

    Of course all the credits for this example belong to you and I will add them on the article/code accordingly.

    So, could you please let me know your thoughts?

    Thanks!

    ReplyDelete
  5. The knowledge of technology you have been sharing thorough this post is very much helpful to develop new idea. here by i also want to share this.
    full stack developer training in pune

    full stack developer training in annanagar

    full stack developer training in tambaram

    full stack developer training in velachery

    ReplyDelete
  6. The knowledge of technology you have been sharing thorough this post is very much helpful to develop new idea. here by i also want to share this.
    Python training in marathahalli
    AWS Training in chennai
    AWS Training in bangalore

    ReplyDelete
  7. Thank you for this post. Thats all I are able to say. You most absolutely have built this blog website into something speciel. You clearly know what you are working on, youve insured so many corners.thanks

    Blueprism training in marathahalli

    Blueprism training in btm

    Blueprism online training

    ReplyDelete
  8. Well somehow I got to read lots of articles on your blog. It’s amazing how interesting it is for me to visit you very often.
    java training in jayanagar | java training in electronic city

    java training in chennai | java training in USA

    ReplyDelete
  9. I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post.is article.
    angularjs-Training in pune

    angularjs-Training in chennai

    angularjs Training in chennai

    angularjs-Training in tambaram

    angularjs-Training in sholinganallur

    ReplyDelete
  10. When I initially commented, I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get several emails with the same comment. Is there any way you can remove people from that service? Thanks.

    AWS Interview Questions And Answers

    AWS Training in Chennai | Best AWS Training in Chennai

    AWS Training in Pune | Best Amazon Web Services Training in Pune

    ReplyDelete
  11. It would have been the happiest moment for you,I mean if we have been waiting for something to happen and when it happens we forgot all hardwork and wait for getting that happened.

    Java training in Bangalore | Java training in Btm layout

    Java training in Bangalore |Java training in Rajaji nagar

    Java training in Bangalore | Java training in Kalyan nagar

    ReplyDelete
  12. This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.

    rpa training in chennai
    rpa training in bangalore
    rpa course in bangalore
    best rpa training in bangalore
    rpa online training

    ReplyDelete
  13. Thanks Admin for sharing such a useful post, I hope it’s useful to many individuals for developing their skill to get good career.
    python training institute in marathahalli
    python training institute in btm
    Python training course in Chennai

    ReplyDelete
  14. I found your blog while searching for the updates, I am happy to be here. Very useful content and also easily understandable providing.. Believe me I did wrote an post about tutorials for beginners with reference of your blog. 
    Devops Training courses
    Devops Training in Bangalore
    Best Devops Training in pune
    Devops interview questions and answers

    ReplyDelete
  15. Greetings. I know this is somewhat off-topic, but I was wondering if you knew where I could get a captcha plugin for my comment form? I’m using the same blog platform like yours, and I’m having difficulty finding one? Thanks a lot.

    Advanced AWS Online Training | Advanced Online AWS Certification Course - Gangboard
    Best AWS Training in Chennai | Amazon Web Services Training Institute in Chennai Velachery, Tambaram, OMR
    Advanced AWS Training in Bangalore |Best AWS Training Institute in Bangalore BTMLA ,Marathahalli

    ReplyDelete