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各种疑难杂症的主要内容,如果未能解决你的问题,请参考以下文章
flutter sdk升级 kotlin升级 gradle升级 使用flutter upgrade命令 以及依赖的各项配置更新 呕心沥血 踩坑无数 专治疑难杂症
flutter sdk升级 kotlin升级 gradle升级 使用flutter upgrade命令 以及依赖的各项配置更新 呕心沥血 踩坑无数 专治疑难杂症