常见 Android 代码兼容性问题及解决方案

本文深入探讨了Android开发中的常见兼容性问题,包括Fragment的onActivityResult不回调、WebView兼容性、版本适配(如Android 5.0至8.0的网络监听和文件共享)以及RelativeLayout布局问题。提供了详细的分析和解决方案,帮助开发者解决在不同系统版本中遇到的问题,提升应用的兼容性和用户体验。
摘要由CSDN通过智能技术生成

前言

感谢大家对这篇文章的支持,我们将深入研究安卓中常见的兼容性问题的原因以及解决方案,主要目录如下:

  1. 如何回调 Fragment 的 onActivityResult()方法;
  2. 监听 ScrollView 滑动底部的兼容问题;
  3. WebView的兼容问题
  4. Android 5.0 监听网络;
  5. Android 7.0 文件共享;
  6. Android 8.0 安装 Apk;
  7. Android 8.0 发送通知
  8. RelativeLayout 常见的布局问题。
  9. 其他

我们来依次研究这些兼容性问题。

###正文

Fragment 的 onActivityResult() 的不回调问题

首先我们写一个小例子帮助我们分析出现这个问题的原因:

创建 MainActivity,内部使用了 MainFragment,在MainFragment中点击按钮,跳转到另外一个 Activity,在 MainActivity 中也有一个按钮,点击也会跳转到另一个 Activity。

创建 SecondActivity,打开一秒后销毁,返回新的 String。

先了解一下我们的布局:

enter image description here

这两个跳转的区别是:分别调用了 Fragment.startActityForResult() 和 Activity.startActivityForResult()。

在 MainFragment 中重写 onActivityResult() 方法,显示返回的字符串:

enter image description here

首先我们点击 Fragment 的按钮,看一下结果:

enter image description here

很明显,我们得到了 SecondActivity 中的字符串,说明调用了 Fragment.startActivityForResult(),在 Fragment 的 onActivityResult() 是可以得到结果的。

然后我们再点击 MainActivity 的按钮,看一下结果:

enter image description here

没有效果!?惊讶之余后仔细思考,把 Activity 和 Fragment 的 startActivityForResult 分开处理,这种设计也是合理的。

我们在开发中大部分情况都是因为在 Fragment 中调用 Activity 的 startActivityForResult 方法,从而引起 onActivityForResult 失效。

例如我曾经写过的代码,封装从手机相册选择图片的公共方法:

enter image description here

因为参数的类型是 Activity,所以 Fragment 调用这个方法的时候是无法回调 onActivityResult 的。

那安卓是怎么做到区分 Fragment 和 Activity 的 startActivityForResult 的呢?我们从源码看一下从 startActivityForResult 到 onActivityResult 的主要流程:

首先 Fragment 的 startActivityForResult 最终调用的是 Fragment 的 startActivityFromFragment 方法:

enter image description here

其中被红线圈起来的地方是我们分析的重点:

  1. allocateRequestIndex 方法,主要把调用的 Fragment 通过键值对的方式保存起来,其中 key 是计算出来的索引值,value 是 Fragment 的 mWho 属性(在相同 FragmentManager 中,具有唯一性),等 onActivityResult 执行的时候,再取出这个 Fragment,执行他的 onActivityResult 方法。
  2. 下一个重点是对 RequestCode 进行了加工,安卓 SDK 区分回调的是 Activity 还是 Fragment,就是通过加工后的 RequestCode,所以即使双方使用了相同 RequestCode 也不会有影响。
  3. ActivityCompat.startActivityForResult 是对历史版本的兼容,调用的还是 Activity 的 startActivityForResult,所以说 RequestCode 加工是 Fragment 独有的。

当跳转的 Activity 销毁后,启动的 Activity 得到结果,执行了 onActivityResult:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        mFragments.noteStateNotSaved();
        // 对加工过的requestCode进行反解
        int requestIndex = requestCode>>16;
        // 如果是Activity,requestIndex会等于0
        if (requestIndex !=0) {
	        // ((requestIndex + 1) << 16)
	        // 因为加工的时候加了1,所以这里减1
            requestIndex--;
			// 通过requestIndex得到fragment.mWho属性
			// 之前的allocateRequestIndex方法作用就在这里
            String who = mPendingFragmentActivityResults.get(requestIndex);
            mPendingFragmentActivityResults.remove(requestIndex);
            if (who == null) {
                Log.w(TAG, "Activity result delivered for unknown Fragment.");
                return;
            }
            // fragment不为空,就执行fragment的onActivityResult
            Fragment targetFragment = mFragments.findFragmentByWho(who);
            if (targetFragment == null) {
                Log.w(TAG, "Activity result no fragment exists for who: " + who);
            } else {
            // 这里还原了RequestCode
            targetFragment.onActivityResult(requestCode & 0xffff, resultCode, data);
            }
            return;
        }
		// 执行Activity的onActivityResult流程
        ActivityCompat.PermissionCompatDelegate delegate =
                ActivityCompat.getPermissionCompatDelegate();
        if (delegate != null && delegate.onActivityResult(this, requestCode, resultCode, data)) {
           
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值