Activity被回收掉之后的网络回调处理

早上来到公司刚打开电脑,就被叫到会议室,召开紧急会议,线上出现重大bug,根据线上日志统计,崩溃率上升了0.3个百分点(我们项目是集成了腾讯Bugly统计日志,有兴趣的同学可以去了解下)。

这个可不得了,听说领导被老板叫过去训了好久,领导憋了一肚子火,我们的日子你大概能想象得到。没办法,那的赶紧找出bug来源,解决掉后赶紧发修复补丁(感谢现在的热修复技术,让我们免除了再次发包的痛苦)。

经过我们的查询,崩溃位置很快就被找到,是一处Fragment中的网络请求回调,在网络请求回调成功后,进行数据填充,报了空指针,造成了崩溃。可是咋看那一句也不可能造成空指针啊,控件findview后已经实例化,不可能为空,数据网络请求成功也不可能为空,那到底是为什么报空呢?测试组和我们对那一部分一起进行了模拟测试,可是未出现崩溃的现象,奇了怪了。突然想到是不是因为我们在公司都是连接的WIFI,信号好,所以没出现线上的问题,我们立即进行测试,切换到弱网环境,果然出现了(这也是在测试阶段我们未发现这个问题的原因,建议大家在测试时要再多种环境下进行测试)。

那到底是为什么呢?结合我们的重现,发现是因为界面被回收了,而网络请求还在线程中进行,当线程请求成功后那就会回调返回数据,但是这个时候界面已经被回收掉了,控件为空了,所以报了空。问题找到后那赶紧解决啊。

既然是因为界面回收掉了,那我们在网络回调后填充数据前进行一个界面是否被回收掉的判断,就像这样:

if (mactivity == null || mactivity.isFinishing()) {
    return;
}

然后进行测试,果然问题解决了,赶紧发补丁吧,领导的怒火终于平息了一些,我们这些开发也松了口气,但是仍旧不能掉以轻心,我们继续紧盯线上日志,要看到问题彻底解决了我们才能放下心里的石头。果然,在发完补丁后一段时间,同样的崩溃问题出现的越来越少了,看来问题解决了,偷偷的看下领导,脸上也开始有笑容了,恩,这一关终于熬过去了。

过了几天,崩溃率也下去了,看来这一问题是彻底解决了,心里的石头这时候才彻底放下。渐渐地大家都忘记了这一问题,毕竟在大家看来这已经是解决了,但是我在看线上日志的时候,突然看到了这一问题,纳尼,还有,虽然很少,只有几例,但是还是存在。我立即偷偷的和几个同事商量这个问题,得出的结果是热修复有一定的失败几率,可能是因为那几个用户热修复补丁加载失败,恩,很有可能,那既然这样大家就不用再多想了,等下次发包用户更新了那就彻底没有这个问题了。

可是我还是不太放心,我又在网上查看相关的文章,资料,终于让我找到一位的文章,链接在这:
(参考文章链接)

主要原因是因为我们的判断不够谨慎,我们只判断了 ==null 和 .isFinishing() 两个条件,点进isFinishing() 方法里面看一下:

/**
 * Check to see whether this activity is in the process of finishing,
 * either because you called {@link #finish} on it or someone else
 * has requested that it finished.  This is often used in
 * {@link #onPause} to determine whether the activity is simply pausing or
 * completely finishing.
 *
 * @return If the activity is finishing, returns true; else returns false.
 *
 * @see #finish
 */
public boolean isFinishing() {
    return mFinished;
}

这个方法主要是返回一个标记值 mFinished ,那我们在Activity 类中全局搜索下这个中介值mFinished ,可以发下他是起始为false,但是只有当activity 调用 finish() 时,在这个 mFinished 值会被置为true :

/**
 * Finishes the current activity and specifies whether to remove the task associated with this
 * activity.
 */
private void finish(boolean finishTask) {
    if (mParent == null) {
        int resultCode;
        Intent resultData;
        synchronized (this) {
            resultCode = mResultCode;
            resultData = mResultData;
        }
        if (false) Log.v(TAG, "Finishing self: token=" + mToken);
        try {
            if (resultData != null) {
                resultData.prepareToLeaveProcess();
            }
            if (ActivityManagerNative.getDefault()
                    .finishActivity(mToken, resultCode, resultData, finishTask)) {
                mFinished = true;
            }
        } catch (RemoteException e) {
            // Empty
        }
    } else {
        mParent.finishFromChild(this);
    }
}

而我们知道 finish() 是主动调用的的,也就是说只有你在代码中调用了 finish() 这个方法,它才会被置为true,也就是说如果系统内存紧张,回收掉了它,那就不会走 finish() 这个方法,这个时候mFinished 还是为false,这个时候用 isFinishing() 判断 的话得不到正确的结果,那这种情况该如何判断呢?在API 17的时候,Google 添加了一个 isDestroyed() 的判断,专门针对这一情况 :

/**
 * Returns true if the final {@link #onDestroy()} call has been made
 * on the Activity, so this instance is now dead.
 */
public boolean isDestroyed() {
    return mDestroyed;
}

所以为了保险起见,我们还需要加上 isDestroyed() 判断,做到万无一失。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    if (mactivity.isDestroyed()) {
        return;
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中,Activity生命周期中表现状态分为以下四种: 1. 运行状态(Running):Activity正在前台运行,用户可以与其进行交互。 2. 暂停状态(Paused):Activity正在后台运行,但仍然可以看到一部分界面。例如,当用户打开了另一个Activity时,当前的Activity会进入暂停状态。 3. 停止状态(Stopped):Activity已经不再可见,但是仍然存在于内存中。例如,当用户按下Back键或Home键时,Activity会进入停止状态。 4. 销毁状态(Destroyed):Activity已经被销毁,其资源已经被回收。例如,当Activity被系统回收或用户主动销毁时。 Activity生命周期涉及的回调函数包括以下几种: 1. onCreate():在Activity第一次创建时调用。 2. onStart():在Activity即将变为可见时调用。 3. onResume():在Activity变为前台并开始接收用户输入时调用。 4. onPause():在Activity失去前台焦点并暂停响应用户输入时调用。 5. onStop():在Activity不再可见时调用。 6. onDestroy():在Activity被销毁时调用。 这些回调函数与Activity的状态变化密切相关。例如,当Activity第一次创建时,系统会调用onCreate()方法;当Activity失去前台焦点并暂停响应用户输入时,系统会调用onPause()方法。在实际开发中,我们可以在这些回调函数中执行一些操作,例如初始化UI界面、注册广播接收器等。 需要注意的是,当Activity由于某种原因从前台退到后台或被销毁时,系统不一定会立即回收其资源。在某些情况下,系统会将其保留在内存中,以便在用户再次打开应用程序时能够更快地启动Activity。因此,我们必须合理地管理Activity的生命周期,避免资源浪费和性能问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值