为了账号安全,请及时绑定邮箱和手机立即绑定

【Android】专治Activity各种疑难杂症

标签:
Android
本篇文章主要是记录Activity各种疑难杂症,在平时使用过程中遇到的坑点,以及Activity使用难点,欢迎各位拍砖。

1.setResult和finish的顺序关系

当ActivtyA通过startActivityForResult启动ActivityB的时候,从ActivityB页面返回并设置setResult的时候,会回调ActivityA的onActivityResult方法,并可以通过setResult传值,有时候会遇到setResult传值不起作用的情况:


webp

image.png


上面这张图我是在SecordActivity的onPause方法里调用的setResult:

@Override
    protected void onPause() {        super.onPause();
        Intent intent = new Intent();
        intent.putExtra("name","来自secord的data");
        setResult(101,intent);
        Log.e("wangkeke","secord---onPause");
    }

可以发现setResult传递name值失败,那么setResult()应该在什么时候调用呢?看下setResult和finish的源码:

    public final void setResult(int resultCode, Intent data) {        synchronized (this) {
            mResultCode = resultCode;
            mResultData = data;
        }
    }    private void finish(int 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(this);
                }                if (ActivityManager.getService()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {                // Empty
            }
        } else {
            mParent.finishFromChild(this);
        }
    }

Activity返回result是在finish的时候,也就是说调用setResult()方法必须在finish()之前。所以在onPause、onStop、onDestroy方法中调用setResult()可能会返回失败。

如果你需要在点击back键的时候setResult,可以用以下写法:

    @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("name","来自secord的data");
        setResult(101,intent);        //下面这行代码会去调用finish方法
        super.onBackPressed();
    }

2.onNewIntent注意事项以及SingleTask的坑

触发时机:activity任务栈中已存在要启动的Activity实例,则不会再创建新实例,而是执行Activity的onNewIntent(intent)方法。

@Override
    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        //更新intent
        setIntent(intent);
}

如果没有调用setIntent(intent),则getIntent()获取的数据可能不是你所期望的。但是使用onNewIntent的参数intent,是可以获得正确的数据的。

注意:对于Activity的启动模式这里不多介绍,但是当要启动的Activity的启动模式设置为SingleTask时,并且启动Activity使用的是startActivityforResult方法,那么此时SingleTask会失效。
具体原因分析点这里!

3.旋转手机屏幕时Activity的生命周期和onConfigurationChanged()的调用时机

我在Android8.0上Activity未配置configChanges时的测试结果如下:

webp

image.png


配置configChanges为android:configChanges="orientation|screenSize"时,结果如下:

webp

image.png


此时Activity不会重新创建,而只会调用onConfigurationChanged()方法。在targetSdkVersion的值小于或等于12时,只需要配置orientation就可以得到同样的结果。


所以旋转手机屏幕时,activity生命周期的变化和configChanges属性有关,配置相关属性就不会重新走onCreate流程,不配置的话就会先走销毁流程,再走onCreate流程。
注:configChanges属性参数如下表:

webp

官网截图.png


4.onSaveInstanceState()和onRestoreInstanceState()

onSaveInstanceState() 和 onRestoreInstanceState() 并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,并不一定会被触发。

当应用遇到意外情况(如:内存不足、按Home键等)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState() 就不会被调用。

onSaveInstanceState()的调用遵循一个重要原则,即当系统存在 “未经你许可” 销毁了我们的 activity 的可能时,则 onSaveInstanceState() 会被系统调用,且调用将发生在 onPause() 之前。

onRestoreInstanceState() 被调用的前提是,activityA “确实” 被系统销毁了,且 activity A 被重新创建。当 activityA 未被重新创建时,该方法不会被调用,onRestoreInstanceState() 在 onStart() 和 onResume() 之间调用。

注意:onRestoreInstanceState()一旦被调用,其参数bundle一定是有值的,而onCreate则不一定。

5. TaskAffinity属性

我们知道,每个APP默认只有一个任务栈,以应用的包名来命名,Activity的TaskAffinity属性可以新建任务栈。

如果单独设置TaskAffinity属性的话是没有任何效果的,只有Activity的launchMode设置成singleTask的时候才会生效的,在AndroidManifest的Activity中可以配置TaskAffinity这个属性。

注意:
1.TaskAffinity的值应该是形如xxx.xxx.xxx的形式,如果没有包含 . 的话是安装不了的;
2.如果不指定TaskAffinity的话,默认的任务栈名称就是应用包名。

注意:采用startActivityForResult的方式启动Activity时,TaskAffinity属性无效!



作者:寒小枫
链接:https://www.jianshu.com/p/7fc6560c5d99


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消