Android高级面试 —— onActivityResult能不能设计成回调?


我觉得这是一个很有趣的问题,有趣的除了题目本身,也在于其引申出的感悟。我们在使用和学习Android Framework相关的内容时,除了要了解其内部实现机制,还要求自己要试着去反思,或者提问其设计的目的,这样才能帮助我们更好的理解和吸收其设计的精髓之处。

1. 你觉得onActivityResult好用吗?

面试官在提出设计问题前可能会先抛砖引玉,先提出这个问题来探一探面试者有没有真正的去体验和总结相关的内容。大部分人可能会说,麻烦!那为什么麻烦呢?首先先看一下onActivityResult是怎么使用的:

 // Activity A
 startActivityForResult(intent, requestCode);

 // Activity B
 setResult(resultCode, intent);

 // Activity A
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(resultCode) {
       ...
    }
 }

从代码中可以看出,onActivityResult存在以下使用的问题:

1)代码处理逻辑分离,容易出现遗漏和不一致的地方

很明显,在使用上startActivityonActivityResult的逻辑是分开的,假如,startActivity的requestCode被修改了,那么onActivityResult的requestCode也要修改,这样就很容易出现修改遗漏而导致不一致的地方。

2)写法不够直观,且结果数据没有类型安全保障

onActivityResult的用法要求Activity A和Activity B需要事先沟通好回传的内容字段和格式,如:

 // Activity B
 Intent intent = new Intent();
 intent.putExtra("result", "true");
 setResult(resultCode, intent);

 // Activity A
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(resultCode) {
       ...
       boolean result = Boolean.valueOf(data.getString("result"));
    }
 }

如果Activity B修改了result的回传格式为boolean,但是又没有通知Activity A修改,这样编译时是不会发现问题,只有在运行时抛出异常了才发现:

 // Activity B
 Intent intent = new Intent();
 intent.putExtra("result", true);  // String修改为boolean
 setResult(resultCode, intent);

 // Activity A
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(resultCode) {
       ...
       // throws exception
       boolean result = Boolean.valueOf(data.getString("result"));
    }
 }

3)当结果种类比较多时,onActivityResult会逐渐臃肿且难以维护

这个问题也是显而易见的,当处理场景较多时,就会出现很多switch-case语句。当然,把相应的case实现抽成方法,可以提高代码的可读性:

 // Activity A
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(resultCode) {
       case PICK_PHOTO_BACK:
           handlePickPhotoBack(data);
       case CAMERA_BACK:
           handleCameraBack(data);
       case CROP_PHOTO_BACK:
           handleCropPhotoBack(data);
       ...
    }
 }

2. onActivityResult能设计成回调吗?

假设onActivityResult可以设计成回调,那么startActivity的代码应该如下:

 // Activity A
 startActivityForResult(intent, new OnResultCallback(){
    @Override
    public void onResult(Intent data) {
       textView.setText(data.getString("result"));
    }
 })

由于匿名内部类会持有外部类的引用,当Activity A被意外销毁时,由于其对象被OnResultCallback可能会导致其无法正常被GC,当Activity B给Activity A回复时,OnResultCallback被调用,新的Activity A2 被恢复,但是onResult方法持有的依旧是被销毁的Activity A的引用,即:

 // Activity A2
 startActivityForResult(intent, new OnResultCallback(){
    @Override
    public void onResult(Intent data) {
       activityA.textView.setText(data.getString("result"));
    }
 })

所以,结论就是不能使用回调,因为Activity的销毁和恢复机制不允许匿名内部类出现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值