告别onActivityResult ,用代理实现Rx方式获取startActivityForResult结果
来源:互联网 发布:淘宝直邮澳洲 编辑:程序博客网 时间:2024/06/05 18:27
尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/74331845, 本文出自:【gengqiquan的博客】
一个多月没写博客了,实在是最近事情特别多。
昨天,在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结果
- android用代理实现Rx方式获取startActivityForResult结果
- startActivityForResult、onActivityResult
- startActivityForResult,onActivityResult
- startActivityForResult+onActivityResult
- 【startActivityForResult】startActivityForResult 和 onActivityResult 问题
- React-native从startActivityForResult中获取结果
- startActivityForResult 和onActivityResult
- startActivityForResult与onActivityResult
- startActivityForResult与onActivityResult
- startActivityForResult与onActivityResult
- Android:startActivityForResult 和 onActivityResult
- startActivityForResult 和 onActivityResult 问题
- startActivityForResult与onActivityResult
- startActivityForResult与onActivityResult
- startActivityForResult 和 onActivityResult 问题
- startActivityForResult与onActivityResult 函数
- startActivityForResult 和 onActivityResult 问题
- 解析上传的EXCEL的2种方式
- 一个java 多线程事例
- 什么是HTML5的媒体查询功能
- commons.beanutils包中BeanUtils类map2bean问题
- @Valid 对表单进行验证
- 告别onActivityResult ,用代理实现Rx方式获取startActivityForResult结果
- mybatis批量插入,传入List。mysql
- ARM协处理器CP15寄存器详解
- 使用Atlassian国际化插件按需、精确定制工具汉化包
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(二)
- 为什么不应该重写service方法?
- 进程与线程模型
- Linux 管道符
- 字典序法生成全排列算法的证明