开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第35天,点击查看活动详情
问题
最近遇到了一个很有趣的问题,为什么不能够用回调的方式使用startActivityForResult呢?如果我们想要用回调的方式使用,有什么问题? 首先我们看一下目前官方的使用方式,如下图所示 其实这个流程很复杂,很不符合高内聚的原则,特别是如果页面的请求很多就会变成如下的情况
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
break;
case 2:
break;
case 3:
break;
.....
}
}
如果我们想要实现成回调的方式呢?
回调实现
参考这篇博客,juejin.im/entry/5b9a6… 有几种实现方式:
- 使用一个代理类,帮忙处理startActivityForResult和onActivityResult,本质上和原生使用方式没有区别,还是必须要在Activity里的onActivityResult 里面手动的调用;
- 使用反射或者AOP,修改onActivityResult的流程,但稳定性和兼容性较差,而且可能会和其他的框架产生冲突;
- 比较推荐的就是这个方法,在Activity里面增加一个空的fragment,通过这个fragment发起请求和接收结果,然后将收到的结果用回调函数传递给Activity。
回调的问题
那么为什么官方不设计成回调的方式呢?像下面这样子,回调的方式有啥问题
startActivityForResult(intent, new CallBack() {
@Override
public void onActivityResult(int resultCode, Intent data) {
}
});
匿名内部类的构造函数 在上述的例子当中,callback是一个匿名内部类,我们都知道匿名内部类会持有外部类的引用,那这个引用是何时传入的呢? 我们通过反射来查看以下匿名内部类的构造函数
private void reflect(Object callback){
Class cl = callback.getClass();
//构造函数
Constructor[] declaredConstructors = cl.getDeclaredConstructors();
for (Constructor constructor:declaredConstructors){
Log.i("构造函数",constructor.toString());
}
}
通过打印可以看到构造函数如下 也就是编译器在编译的时候替我们生成了一个构造函数,并且将对应的activity当作参数传入。
Activity被销毁的场景 若我们考虑下面这种情况,当A使用回调的方式跳转到B,此时由于某种原因A被销毁了,然后当B执行完成返回结果,系统会重新创建A1,而callback里面持有的是A引用,并不会对A1产生作用,这显然不是我们想要的结果。
当activity被重建,我们可以通过反射,将新的activity重新set进去,这样callback引用的就是重建后的新的activity了。
Class cl = callback.getClass();
Field[] fields = cl.getDeclaredFields();
for(Field f : fields) {
try {
f.setAccessible(true); // 设置些属性是可以访问的
String type = f.getType().toString(); // 得到此属性的类型
String name = f.getName();// 得到属性的名称
if(type.equals(FirstActivity.class.toString())) {
f.set(callback, this.getActivity());
}
Log.i("字段信息", type + ", " + name);
} catch (Exception e) {
e.printStackTrace();
}
}
结论
在Activity当中增加一个空的fragment可以解决此问题,但对于Activity销毁和重建的场景则需额外处理,由于反射会损耗性能, 初步想法是增加Activity生命周期的感知能力,当感知到Activity有销毁重建的动作,则使用反射重新设置一下。
今天的文章回调的方式使用startActivityForResult分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14305.html