回调的方式使用startActivityForResult

回调的方式使用startActivityForResult问题 最近遇到了一个很有趣的问题,为什么不能够用回调的方式使用startActivityForResul

开启掘金成长之旅!这是我参与「掘金日新计划 · 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… 有几种实现方式:

  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有销毁重建的动作,则使用反射重新设置一下。

今天的文章回调的方式使用startActivityForResult分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14305.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注