Android专治Activity各种疑难杂症

Posted 寒小枫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android专治Activity各种疑难杂症相关的知识,希望对你有一定的参考价值。

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

1.setResult和finish的顺序关系

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

上面这张图我是在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时的测试结果如下:

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

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


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

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属性无效!

以上是关于Android专治Activity各种疑难杂症的主要内容,如果未能解决你的问题,请参考以下文章

这篇文章,专治MQ中间件各种疑难杂症

专治疑难杂症win7电脑登录账户后黑屏(只有鼠标箭头)问题

flutter sdk升级 kotlin升级 gradle升级 使用flutter upgrade命令 以及依赖的各项配置更新 呕心沥血 踩坑无数 专治疑难杂症

flutter sdk升级 kotlin升级 gradle升级 使用flutter upgrade命令 以及依赖的各项配置更新 呕心沥血 踩坑无数 专治疑难杂症

Android疑难杂症之android:configChanges="orientation" 无效

移动端兼容宝典大全,专治各种不适