Rxjava Starter Series four, responsive programming in Android
In the introductory series, I've basically introduced how Rxjava is used. But as an Android developer, how do you make Rxjava work for you? This blog I will introduce to Android development for the Rxjava of the use of the scene.
Rxandroid
Rxandroid is a rxjava extension for Android. With Rxandroid you can make Android easier to develop.
First, Rxandroid provides the androidschedulers, which you can use to switch Android threads. Do you want to run the code on the UI thread? No problem, use Androidschedulers.mainthread () to:
retrofitService.getImage(url) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
If you have created a handler, you can also use Handlerthreadscheduler to create a scheduler associated with your handler.
Next, the androidobservable is available in Rxandroid, which provides a number of features that can be used with the Android app lifecycle. For example, Bindactivity () and Bindfragment () two methods, The Androidschedulers.mainthread () thread is used by default to execute the Observer code, and observable automatically stops sending new events when activity or fragment exits.
AndroidObservable.bindActivity(this, retrofitService.getImage(url)) .subscribeOn(Schedulers.io()) .subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
I also like the Androidobservable.frombroadcast () method, It helps you create a observable object that works with Broadcastreceiver. Here's how to use observable to monitor network status changes:
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);AndroidObservable.fromBroadcast(context, filter) .subscribe(intent -> handleConnectivityChange(intent));
Finally, we introduce the Viewobservable object, which can be used to bind the view. For example, you can use the Viewobservable.clicks () method to listen to the view's click events, using the Viewobservable.text () method to listen for TextView content change events.
false) .subscribe(view -> handleClick(view));
Retrofit
There is a very well-known project that supports Rxjava: Retrofit, a library of simplified HTTP requests designed for Android. Typically, you can add a callback object to define an asynchronous method call:
@GET("/user/{id}/photo")void getUserPhoto(@Path("id"int id, Callback<Photo> cb);
But with Rxjava, you can replace the incoming callback object by returning the observable object:
@GET("/user/{id}/photo")Observable<Photo> getUserPhoto(@Path("id"int id);
Once you've got the observable object, you can manipulate it, not just to get the previous data stream, you can even change the data stream again.
Retrofit's support for observable makes it easy for retrofit to combine multiple rest requests. For example, we have a request to get a photo, and another request is to get the metadata. We merged two requests through the observable:
Observable.zip( service.getUserPhoto(id), service.getPhotoMetadata(id), (photo, metadata) -> createPhotoWithData(photo, metadata)) .subscribe(photoWithData -> showPhoto(photoWithData));
In the Rxjava entry System II, I used Flatmap to do a similar example. Here I want to show how easy it is to combine multiple retrofit requests through retrofit.
History code
Although retrofit supports Rxjava, what happens to other libraries that you use in your project that do not support Rxjava? What do you want to do with some historical legacy code in the form of Rxjava? Can you turn the history code into a Rxjava form without modifying the code?
Observable.just () and observable.from () can generally help you solve these problems:
privateoldMethod() { ... }publicnewMethod() { return Observable.just(oldMethod());}
If the Oldmethod () method executes very quickly, there is usually nothing wrong with doing so. But what if Oldmethod () executes very slowly? When you pass Oldmethod () to the Observable.just () method, because Oldmethod () Performing too slowly may cause the main thread to block.
To avoid this problem, I often use defer () to wrap code that runs slowly:
privateslowBlockingMethod() { ... }publicnewMethod() { return Observable.defer(() -> Observable.just(slowBlockingMethod()));}
Now, the call to Newmethod () will not block unless you subscribe to the returned observable object.
Life cycle
I left the hardest part to the end. How do I handle the life cycle of an activity using Rxjava? Here are two main challenges:
How do I maintain a subscription relationship when the environment configuration changes (such as screen rotation)?
Suppose you want to send a network request via retrofit and display the results to the ListView. If the user rotates the screen during the process, do you still want to keep doing this and how to keep it?
What if resolving observable holds a context object that could cause a memory leak?
The problem is that the context object is maintained when the subscription is created, which is easily triggered when the view is manipulated. If observable doesn't end in time, you may be wasting more and more memory.
Unfortunately, there is no clear way to solve these two problems, but you can follow the guidance below to try to avoid the use of Android Rxjava will encounter the pit.
The first problem can be solved using the Rxjava built-in caching mechanism, where you can perform unsubscribe and resubscribe.cache mechanisms on the same observable object to continue the previous request. Even if you have unsubscribed. This means that you can establish a subscription relationship again when the activity is rebuilt:
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(photo));
The second problem can be solved by releasing the subscription relationship in the activity's specific life cycle function. A very common pattern is to use Compositesubscription to hold all subscription, and then in OnDestroy () or cancel the subscription in the Ondestroyview () method.
private CompositeSubscription mCompositeSubscription new CompositeSubscription();privatevoiddoSomething() { mCompositeSubscription.add( AndroidObservable.bindActivity(this, Observable.just("Hello, World!")) .subscribe(s -> System.out.println(s)));}@OverrideprotectedvoidonDestroy() { super.onDestroy(); mCompositeSubscription.unsubscribe();}
You can still do it a little more general, you can create a Compositesubscription object in the Activity/fragment base class, using unsubscribe methods in related life cycle functions such as ondestory of the base class.
Note that once you call the Compositesubscription.unsubscribe () method, the Compositesubscription object is unavailable, and if you want to use Compositesubscription, You must re-create a new object.
There is a need to add some code to solve both of the above problems. I hope that some developers will tell me a better solution that does not need to add so many template code.
Summarize
Rxandroid has not fully adapted to the Android platform, after all, Rxjava is a very new project, Rxandroid is a period of time to improve. Rxandroid is still in the development phase and there is currently no good example to show. I bet a year later, Some of the suggestions mentioned in this blog may no longer apply.
At the same time, I found that Rxjava not only simplifies your code logic, it also makes your code interesting and elegant.
Original link
Grokking RxJava, part 4:reactive Android
Rxjava Starter Series four, responsive programming in Android