Learning opportunity
I have been in touch with RxJava for some time, but I always feel that I am still in the beginning stage of using and understanding RxJava. On the one hand, it has something to do with the fact that you didn’t go deep enough to learn RxJava, because you used some basic operators, and you can boast that you know RxJava. On the other hand, RxJava event-driven programming ideas, the author has always understood the bad.
I don’t think it makes much sense to just learn operators. In fact, I’ve spent a lot of time learning operators before, only to find that it’s not working because I still don’t know when to use the RxJava operator properly. I asked my friend, he said you can try to read the source code of some Rx open source projects, from simple start, to learn the convenience Rx brings, and the change of way of thinking.
This same friend again recommended RxActivityResult to me. Code is not much, very suitable for me to learn. So let’s go to startActiviityForResult() the other way around.
Introduction to the
RxActivityResult is another Rx open source masterpiece from VictorAlbertos. The library was recently updated to fully support AndroidX. When you’ve had enough of onActivityResult() accepting data from a system (such as a camera) or your own callback, try this library and say goodbye to onActivityResult(). A brief description of the library’s features:
- The incoming
Activity
或Fragment
Can be opened in any classIntent
. - The data is encapsulated in an observable
Observable
In return, means can continue to enjoyRxJava
Operator convenience.
use
- First under Project
build.gradle
addmaven
Rely on.
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io"}}}Copy the code
- Under the background of the app
build.gradle
addRxActivityResult
和RxJava
Rely on.
implementation 'com. Making. VictorAlbertos: RxActivityResult: 0.5.0-2 x'
implementation 'the IO. Reactivex. Rxjava2: rxjava: 2.2.3'
Copy the code
- After adding the dependency, we need to set the
Application
Registered inRxActivityResult
。
class MyApp : Application() {
override fun onCreate(a) {
super.onCreate()
RxActivityResult.register(this)}}Copy the code
- in
MainActivity
Click the button to jump toMain2Activity
. Here is a code example
@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this, Main2Activity::class.java)
btnJump
.setOnClickListener {
RxActivityResult
.on(this)
.startIntent(intent)
.map {
it.data()
}
.subscribe {
val extra = it.getStringExtra("resultData")
println(extra)
}
}
}
Copy the code
- in
Main2Activity
Click the button to send back data.
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
btnResult.setOnClickListener {
val intent = intent
intent.putExtra("resultData"."I'm the data back.")
setResult(Activity.RESULT_OK, intent)
finish()
}
}
Copy the code
Ok, that’s it for a simple use. If used with RxBinding, you can make your code more Rx and ensure the integrity of the flow of action events.
btnJump
.clicks()
.throttleFirst(500, TimeUnit.MILLISECONDS)
.map { Intent(this, Main2Activity::class.java)}
.flatMap {
RxActivityResult.on(this)
.startIntent(it)
}
.map{ it.data() }
.subscribe {
val stringExtra = it.getStringExtra("resultData")
println(stringExtra)
}
Copy the code
With a few lines of code, you say goodbye to onActivityResult() and can receive the returned data. Here are two questions:
- in
Application
Why register in. onActivityResult()
Who is the concrete implementation of.
Source code analysis
- So let’s take a look first
Application
Register in.
class MyApp:Application() {
override fun onCreate(a) {
super.onCreate()
RxActivityResult.register(this)}}Copy the code
To briefly introduce ActivityLifecycleCallbacks, it is defined in the Application an interface that can be used to monitor all of the Activity lifecycle callback, the callback and prior to the Activity life cycle. Using ActivityLifecycleCallbacks can also judge the current App in the foreground or the background. Please refer to the specific usage by yourself.
RxActivityResult. The register () is actually returned to the library writers define ActivitiesLifecycleCallbacks class. By looking at the source code, we know that the Application object passed in is used to register the listening Activity lifecycle.
Now that you’ve answered the first question, register RxActivityResult in your Application so that you can listen to the life cycle of all activities. After all, it makes no sense to go to startIntent() after onPause.
- Then look at the
Activity
Specific use of
RxActivityResult
.on(this) / / step 1
.startIntent(intent) / / step 2
.map { it.data }
.subscribe {
val extra = it.getStringExtra("resultData")
println(extra)
}
Copy the code
- call
on()
The incomingthis
Object to determine whether a user is fromActivity
orFragment
The operation of the startIntent()
Method will eventually be calledstartHolderActivity()
.
@SuppressLint("CheckResult")
private Observable<Result<T>> startHolderActivity(Request request, @Nullable OnPreResult onPreResult) {
OnResult onResult = uiTargetActivity ? onResultActivity() : onResultFragment(); // Determine the Intent launched from an Activity or Fragment
request.setOnResult(onResult);
request.setOnPreResult(onPreResult);
// Set the request object
HolderActivity.setRequest(request);
// From the current Activity, start HolderActivity
activitiesLifecycle.getOLiveActivity().subscribe(new Consumer<Activity>() {
@Override
public void accept(Activity activity) throws Exception {
activity.startActivity(new Intent(activity, HolderActivity.class) .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)); }});/ / return PublishSubject
return subject;
}
Copy the code
Look at the first onResultActivity ()
private OnResult onResultActivity(a) {
return new OnResult() {
@Override
public void response(int requestCode, int resultCode, Intent data) {
if (activitiesLifecycle.getLiveActivity() == null) return;
//If true it means some other activity has been stacked as a secondary process.
//Wait until the current activity be the target activity
if(activitiesLifecycle.getLiveActivity().getClass() ! = clazz) {return;
}
T activity = (T) activitiesLifecycle.getLiveActivity();
// Launch Result
subject.onNext(new Result<>(activity, requestCode, resultCode, data));
subject.onComplete();
}
@Override
public void error(Throwable throwable) { subject.onError(throwable); }}; }Copy the code
Create an OnResult object and emit the Result Result in Response ().
- Subject
Subject
It can be a data sourceObservable
Can also be a subscriber to the dataObserver
.
public abstract class Subject<T> extends Observable<T> implements Observer<T> {... }Copy the code
As you can see from the source code, the Subject is actually an Observable, but it implements the Observer interface and can emit and terminate transmitting data through onNext, onComplete, and onError methods. The author uses a PublischSubject to publish Result. The PublischSubject only accepts data published after being subscribed.
- Look at the
HolderActivity
The operation
-
Open the actual Intent object in onCreate()
-
Close HolderActivity in onActivityResult and send back data in onDestroy
@Override
protected void onDestroy(a) {
super.onDestroy();
if(onResult ! =null)
onResult.response(requestCode, resultCode, data);
}
Copy the code
To summarize the general logic, for example, in our shopping process, we place an order for books from JINGdong, and the shopkeeper asks his employee, Xiao Wang, to search for books in the warehouse. And package and send express (publischsubjection.onnext (Result())). A Courier delivers the book to the customer’s door, and the customer checks the purchase information (intent.getStringExtra(“resultData”)) to get the book if the information is correct.
Summary and Reflection
Through analyzing RxActivityResult library of simple, understand the ActivityLifecycleCallbacks and PublischSubject in concrete using three sides in the library. You also learned about some RxJava operators, such as the takeWhile filter operator. More importantly, I usually get data from onActivityResult() without encountering RxActivityResult (), which breaks my previous understanding that it is possible to process onActivityResult() data in this way.
When I am pleased with the results of the current learning method (use – source analysis – summary). My friend’s words alerted me. Reading the source code is just the first step. More importantly, the master of the idea, standing in a higher Angle to think, why the design. You should not just be satisfied with the basic source code analysis, but the design behind it is the essence.
If only to the source analysis, according to the author’s ideas to clear away the clouds, the progress is limited. I need to think further, which is what I need to learn next.