回调的方式使用startActivityForResult

问题

最近遇到了一个很有趣的问题,为什么不能够用回调的方式使用startActivityForResult呢?如果我们想要用回调的方式使用,有什么问题?
首先我们看一下目前官方的使用方式,如下图所示
在这里插入图片描述
其实这个流程很复杂,很不符合高内聚的原则,特别是如果页面的请求很多就会变成如下的情况

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            .....          
        }
    }

如果我们想要实现成回调的方式呢?

回调实现

参考这篇博客,https://juejin.im/entry/5b9a6e3cf265da0adc18b6f7
有几种实现方式:

  1. 使用一个代理类,帮忙处理startActivityForResult和onActivityResult,本质上和原生使用方式没有区别,还是必须要在Activity里的onActivityResult
    里面手动的调用;
  2. 使用反射或者AOP,修改onActivityResult的流程,但稳定性和兼容性较差,而且可能会和其他的框架产生冲突;
  3. 比较推荐的就是这个方法,在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有销毁重建的动作,则使用反射重新设置一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值