In layman's Rxjava four-use responsive programming in Android

Source: Internet
Author: User

Original link

In the first-in-one article, I've probably introduced how Rxjava is used. I'll show you how to use Rxjava in Android.

Rxandroid

Rxandroid is an extension of Rxjava for Android platforms. It contains tools that simplify the development of Android.

First, Androidschedulers provides a scheduler for the threading system of Android. Need to run some code in the UI thread? Very simple, only need to use Androidschedulers.mainthread ():

retrofitService.getImage(url)    .subscribeOn(Schedulers.io())    .observeOn(AndroidSchedulers.mainThread())    .subscribe(bitmap -> myImageView.setImageBitmap(bitmap));

If you have created your own handler, you can use HandlerThreadScheduler1 to link a scheduler to your handler.

The next thing to talk about is androidobservable, which provides multiple features to match Android's life cycle. The Bindactivity () and Bindfragment () methods use Androidschedulers.mainthread () to execute the Observer code by default. Both methods notify the observer to stop sending new messages at the end of the activity or fragment.

AndroidObservable.bindActivity(this, retrofitService.getImage(url))    .subscribeOn(Schedulers.io())    .subscribe(bitmap -> myImageView.setImageBitmap(bitmap);

I like it myself. The Androidobservable.frombroadcast () method, which allows you to create a observable object similar to Broadcastreceiver. The following example shows how to be notified when the network changes:

new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);AndroidObservable.fromBroadcast(context, filter)    .subscribe(intent -> handleConnectivityChange(intent));

The final introduction is viewobservable, which can be used to add some bindings to the view. If you want to receive an event every time you click on the view, you can use Viewobservable.clicks (), or you want to listen for TextView content changes, you can use Viewobservable.text ().

false)    .subscribe(view -> handleClick(view));
Retrofit

The famous retrofit library has built-in support for Rxjava. Typically, a call can be made by using a callback object to get the result asynchronously:

@GET("/user/{id}/photo")void getUserPhoto(@Path("id"int id, Callback<Photo> cb);

With Rxjava, you can return directly to a observable object.

@GET("/user/{id}/photo")Observable<Photo> getUserPhoto(@Path("id"int id);

Now you are free to use the observable object. Not only can you get the data, you can also transform it.
Retrofit's support for observable makes it easy to combine multiple rest requests. For example, we have a request to get a photo, and a request is to get the metadata, we can send these two requests concurrently, and wait for two results to return after the processing:

Observable.zip(    service.getUserPhoto(id),    service.getPhotoMetadata(id),    (photo, metadata) -> createPhotoWithData(photo, metadata))    .subscribe(photoWithData -> showPhoto(photoWithData));

In the second article I showed a similar example (using Flatmap ()). Here I just want to show how easy it is to combine multiple rest requests using Rxjava+retrofit.

Legacy code, running extremely slow code

Retrofit can return observable objects, but what if the other libraries you use do not support this? or an internal code, you want to convert them into observable? What's the easy way?

Most of the time Observable.just () and Observable.from () can help you create Observable objects from legacy code:

privateoldMethod() { ... }publicnewMethod() {    return Observable.just(oldMethod());}

In the above example, if Oldmethod () is fast enough, it's not a problem, but what if it's slow? Calling Oldmethod () will block the thread on which he is located.
To solve this problem, refer to the method I have been using – using defer () to wrap the slow code:

privateslowBlockingMethod() { ... }publicnewMethod() {    return Observable.defer(() -> Observable.just(slowBlockingMethod()));}

Now, the call to Newmethod () is not blocked unless you subscribe to the returned observable object.

Life cycle

I left the hardest in the end. How is the life cycle of the activity handled? There are two main questions:
1. Continue the previous subscription after the configuration changes (such as turning the screen).

For example, you use retrofit to make a rest request, and then you want to show the results in the ListView. What if the user spins the screen when the network request is made? Of course you want to continue with the request, but what?

2.Observable holds context-led memory leaks

The problem is that when you create a subscription, you hold a reference to the context in some way, especially when you interact with the view, which is too easy to happen! If the observable does not end in time, the memory footprint will become larger.
Unfortunately, there is no silver bullet to solve these two problems, but here are some guidelines you can refer to.

The solution to the first problem is to use the Rxjava built-in caching mechanism so that you can perform unsubscribe/resubscribe on the same observable object without having to run the observable code repeatedly. The cache () (or Replay ()) will continue to execute the network request (even if you call unsubscribe and will not stop). This means that you can create a new observable object from the return value of the cache () when the activity is recreated.

Observable <Photo> request = Service.getuserphoto (ID). cache (); Subscription sub = request.subscribe (photo, Handleuserphoto (photo)); //... When the Activity is being recreated ...  Sub.unsubscribe (); //... Once the Activity is recreated ...  Request.subscribe (photo) Handleuserphoto  

Note that the two sub is the same cached request that was used. Of course where to store the result of the request or do it yourself, and all other life-cycle-related solutions A tiger must be stored somewhere outside the life cycle. (retained fragment or singleton, etc.).

A solution to the second problem is to unsubscribe at some point in the life cycle. A very common pattern is to use Compositesubscription to hold all subscriptions, and then cancel all subscriptions in OnDestroy () or Ondestroyview ().

private CompositeSubscription mCompositeSubscription = new CompositeSubscription();private void doSomething() { mCompositeSubscription.add( AndroidObservable.bindActivity(this, Observable.just("Hello, World!")) .subscribe(s -> System.out.println(s)));}@Overrideprotected void onDestroy() { super.onDestroy(); mCompositeSubscription.unsubscribe();}

You can create a Compositesubscription object in the base class of activity/fragment and use it in subclasses.

Attention! Once you call Compositesubscription.unsubscribe (), the Compositesubscription object is unavailable, and if you want to use Compositesubscription, You have to create a new object.

The solution for both problems requires adding extra code, and if anyone has a better plan, please let me know.

Summarize

Rxjava is still a very new project, Rxandroid. Rxandroid is still active in development, and there are few good examples. I bet a year from now some of my suggestions will be considered obsolete.

In layman's Rxjava four-use responsive programming in Android

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.