告别onActivityResult ,用代理实现Rx方式获取startActivityForResult结果
Posted gengqiquan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了告别onActivityResult ,用代理实现Rx方式获取startActivityForResult结果相关的知识,希望对你有一定的参考价值。
尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/74331845, 本文出自:【gengqiquan的博客】
这个库已经废弃,请移步用代理获取startActivityForResult结果
这个库已经废弃,请移步用代理获取startActivityForResult结果
这个库已经废弃,请移步用代理获取startActivityForResult结果
一个多月没写博客了,实在是最近事情特别多。
昨天,在review 公司项目代码的时候发现onActivityResult方法真的好烦,太影响代码的阅读了,而且编写的时候也需要到处切code位置。于是就有了这篇博客和RxActivityResult 这个库。
大概的调用方式就是这样的
RxActivityResult.with(MainActivity.this).putString("key", "笑一个")
.startActivityWithResult(new Intent(MainActivity.this, SecondActivity.class))
.subscribe(new Consumer<Intent>()
@Override
public void accept(Intent intent) throws Exception
tv.setText(intent.getStringExtra("msg"));
);
源码大家直接到链接看好了,这篇博客主要是聊聊思路
要想完全告别onActivityResult(),有两种方案
1、使用进程注入的方式hook系统的activity数据发送,这种方案比较复杂,用到ndk知识,需要在源码下编译应用,不适合大部分人。
2、利用代理进行跳转事件转发代理和 onActivityResult()事件代理接收后再通知委托者。
这里我们用第二种,代理对象有两个供选择,一个是activity,每次startActivityForResult的时候打开的使我们的代理activity(ProxyActivity),然后由ProxyActivity进行转发intent,并在ProxyActivity里进行 onActivityResult()事件处理,然后通知委托者;所以我们需要在manifest进行注册,并且需要合理的管理activity的堆栈。
一个是利用Fragment,这就需要将Fragment加载到activity上,否则发起intent的时候会报 not attach activity 异常,再一个就是需要兼容v4和app两种情况,当然,如果大家的项目里的基类是固定的一种就不需要了。
下面我们来看看具体实现方式
首先构建一个请求容器对象,用来存放被转发的intent和请求识别码
public class Request
Intent intent;
int code;
public Request(Intent intent, int code)
this.intent = intent;
this.code = code;
再构建一个结果容器对象,用来存放onActivityResult返回的结果和请求识别码
public class Result
Intent intent;
public Result(Intent intent, int code)
this.intent = intent;
this.code = code;
int code;
然后我们的返回结果是要以RxJava的方式传递给委托者的。这里我们可以参考rxbus的实现方式
构建一个subject
static PublishSubject<Result> subject = PublishSubject.create();
然后我们需要把Fragment加载到Activity上,这就需要有一个界面控件ID和一个FragmentManager,FragmentManager我们可以从委托者获取,根据activity和fragmentActivity的不同决定获取不同的FragmentManager,这个控件ID怎么来呢?熟悉android源码的同学可能就知道了,每个界面的根布局其实都是同一个系统ID(android.R.id.content)这个ID其实可以用来做很多事,比如透明状态栏时软键盘不顶起布局的时候可以用来强制位移布局,或者自己做伪分屏。
接下来就是创建一个代理fragment并且把请求委托给它
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;
这里的请求识别码我们直接通过求intent的hash值来得到。
在代理fragment里进行转发intent和转发返回结果操作
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;
通过subject进行发送
protected static void post(Result result)
if (result.intent != null)
subject.onNext(result);
else
subject.onError(new Exception("intent is null"));
根据请求识别码进行筛选
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;
);
这样就得到了委托者所需要的返回结果了。
完整的示例代码、源码及gradle依赖方式请看https://github.com/gengqiquan/RxActivityResult
有什么建议的可以留言喔
如果我的博客对您有帮助,请留言鼓励下或者点个赞吧!
我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。
以上是关于告别onActivityResult ,用代理实现Rx方式获取startActivityForResult结果的主要内容,如果未能解决你的问题,请参考以下文章
告别 LuaGoWasm 插件,是时候用低代码 API 网关了