Say goodbye to onActivityResult and use proxy to implement Rx to get the result of startActivityForResult

Respect for other people's work results, reprinted please indicate the source: http://blog.csdn.net/gengqiquan/article/details/74331845 This article is from: [gengqiquan's blog]
I haven't blogged for more than a month. It's really a lot of things recently.
Yesterday, when review ing the company's project code, I found that the onActivityResult method is really annoying. It affects the reading of the code too much, and it also needs to be written in all code locations. So there's this blog and RxActivityResult This library.

Probably that's the way it's called.

  RxActivityResult.with(MainActivity.this).putString("key", "Give me a smile")
                        .startActivityWithResult(new Intent(MainActivity.this, SecondActivity.class))
                        .subscribe(new Consumer<Intent>() {
                            @Override
                            public void accept(Intent intent) throws Exception {
                                tv.setText(intent.getStringExtra("msg"));
                            }
                        });

Source code you go directly to the link to see, this blog is mainly to chat ideas.

There are two ways to say goodbye to onActivityResult ().
1. Active data transmission of hook system by process injection is very complex. It needs to be compiled and applied under source code, which is not suitable for most people.
2. Use proxy to forward jump events and onActivityResult () event proxy to notify the principal after receiving.
Here we use the second kind, the proxy object has two choices, one is activity, which opens our proxy activity every time we start activity for Result, then forwards intent by Proxy Activity, and processes onActivity Result () event in Proxy Activity, and then notifies the principal; so we need to register in manifest. And we need to manage the activity stack reasonably.
One is to use Fragment, which needs to be loaded into activity, otherwise the intent will not attach activity exception, and the other is to be compatible with v4 and app, of course, if the base class in your project is a fixed one, it will not be needed.

Let's take a look at the implementation.
First, a request container object is constructed to store the forwarded intent and request identification code.

public class Request  {
    Intent intent;
    int code;

    public Request(Intent intent, int code) {
        this.intent = intent;
        this.code = code;
    }


}

Build a result container object to store the result and request identifier returned by onActivityResult

public class Result {
    Intent intent;

    public Result(Intent intent, int code) {
        this.intent = intent;
        this.code = code;
    }

    int code;


}

Then our return result is to be passed to the client in RxJava. Here we can refer to the implementation of rxbus
Constructing a subject

 static PublishSubject<Result> subject = PublishSubject.create();

Then we need to load Fragments into Activity, which requires an interface control ID and a FragmentManager. FragmentManager can be obtained from the client. According to the different decisions of activity and fragmentActivity, we can get different FragmentManagers. How does this control ID come? Students familiar with the Android source code may know that the root layout of each interface is in fact. The same system ID (android.R.id.content) can actually be used to do a lot of things, such as force displacement layout when the soft keyboard does not hold up the layout when the transparent status bar, or make false splitting.

Next, create a proxy fragment and delegate the request to it

            final Request request = new Request(intent, intent.hashCode());
                final V4Fragment v4Fragment = new V4Fragment();
                v4Fragment.setRequest(request);
                v4Transaction.replace(android.R.id.content, v4Fragment)
                        .commitAllowingStateLoss();
                v4Transaction = null;

The request identifier here is obtained directly by finding the hash value of intent.

Forwarding intent and forwarding return result operation in proxy fragment

public class V4Fragment extends Fragment {
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            if (request != null) {
                RxActivityResult.post(new Result(data, request.code));
            }
            request = null;
            this.getActivity().getSupportFragmentManager().beginTransaction().detach(this).commit();
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    Request request;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (request != null) {
            Intent intent = request.intent;
            startActivityForResult(intent, 0);
        }
    }

    public void setRequest(Request request) {
        this.request = request;
    }
}

Send through subject

  protected static void post(Result result) {

        if (result.intent != null) {
            subject.onNext(result);
        } else {
            subject.onError(new Exception("intent is null"));
        }
    }

Screening Based on Request Identification Code

return subject.filter(new Predicate<Result>() {
                @Override
                public boolean test(Result result) throws Exception {
                    return request.code == result.code;
                }
            }).map(new Function<Result, Intent>() {
                @Override
                public Intent apply(Result result) throws Exception {
                    return result.intent;
                }
            });

In this way, the return result required by the client is obtained.

See the complete sample code, source code, and gradle dependencies https://github.com/gengqiquan/RxActivityResult

What suggestions can I leave a message?

If my blog is helpful to you, please leave a message to encourage or praise it.

I built a QQ group (group number: 121606151) to discuss and exchange Android technology issues. If you are interested, you can make progress together.

Keywords: Fragment Android Gradle github

Added by MikeL on Mon, 17 Jun 2019 00:07:04 +0300