BUG小结

来源:互联网 发布:centos升级后黑屏 编辑:程序博客网 时间:2024/04/28 09:27

今天遇到一个bug,现象是Activity启动显示后,锁屏(此时Activity发了一条Message),

然后亮屏在解锁页面(一直亮着)

30秒后Handler处理Message>>调用了onTitleBackPressed里的onBakPressed方法,造成的崩溃:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState              at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1832)              at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:774)              at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:178)              at com.cmcm.onews.ui.********kVideoActivity.access$101(*****Activity.java:34)              at com.cmcm.onews.ui.**************Activity$2.onTitleBackPressed(*****Activity.java:257)

通过在AS打log(关键词GC |***ActivityLog)发现:

03-11 00:56:09.908 D/***ActivityLog: onResume: 03-11 00:56:12.644 D/***ActivityLog: onPause: 03-11 00:56:12.677 D/***ActivityLog: onSaveInstanceState: 03-11 00:56:12.691 D/***ActivityLog: onStop: 03-11 00:56:30.932 I/art: Background sticky concurrent mark sweep GC freed 36589(2MB) AllocSpace objects, 39(1616KB) LOS objects, 12% free, 23MB/26MB, paused 3.832ms total 101.098ms03-11 00:56:40.533 D/***ActivityLog: onTitleBackPressed: 

直接原因是:

在生命周期onSaveInstanceState、onStop之后,人为调用了FragmentActivity的onBackPress()方法

(本例中是Handler处理Message时调用),

然后执行FragmentManager里的checkStateLoss()引起的Bug

private void checkStateLoss() {        if (mStateSaved) {            throw new IllegalStateException(                    "Can not perform this action after onSaveInstanceState");        }        if (mNoTransactionsBecause != null) {            throw new IllegalStateException(                    "Can not perform this action inside of " + mNoTransactionsBecause);        }    }
查看mStateSaved设置为true的地方,发现FragmentManager有两个地方

static final boolean HONEYCOMB = android.os.Build.VERSION.SDK_INT >= 11;Parcelable saveAllState() {                if (HONEYCOMB) {               mStateSaved = true;        }.....}
public void dispatchStop() {          mStateSaved = true; }

然后分别在源代码FragmentActivity中调用

protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        Parcelable p = mFragments.saveAllState();}       
 protected void onStop() {        super.onStop();        mStopped = true;        mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);        mFragments.dispatchStop(); }
所以生命周期走了onSaveInstanceState 和 onStop,都会将checkStateLoss 中的mStateSaved设置为true

(曾经想把onSaveInstanceState重载,写成空方法,所以也不能解这个崩溃,FragmentActivity的特别之处。。。)


解决方法:

因此,最后的解决方法回到业务逻辑上,我们在onTitleBackPressed里想退出当前的Activity,

那么不去调用onBackPressed方法(从而不checkStateLoss()),直接调用finish方法,崩溃解决。。

从中得出的经验是如果是FragmentActivity,那么手动调用onBackPressed方法,

需要注意会不会出现在onSaveInstanceState 和 onStop之后调用(普通Activity也需要注意)

有可能出现崩溃java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState


另外,亮屏在解锁页面,报IllegalStateException异常之后,解锁,Activity直走到onStop后重新启动onCreate(没有走onDestory)

从03-11 00:56:30.932 I/art: Background sticky concurrent mark sweep GC freed 36589(2MB) AllocSpace objects, 39(1616KB) LOS objects日志看出来

猜测是GC回收了Activity(App process killed),然后User navigates to the activity,重启Activity

(Activity生命周期图的左半部分)


参考:

https://developer.android.com/guide/components/activities/activity-lifecycle.html

Android系统那些重要的LOG

Fragment相关







0 0
原创粉丝点击