[Skill]慎用onBackPressed()

来源:互联网 发布:淘宝一个月赚5000难吗 编辑:程序博客网 时间:2024/05/24 01:43

慎用onBackPressed()

Android中在按下back键时会调用到onBackPressed()方法,onBackPressed相对于finish方法,还做了一些其他操作,而这些操作涉及到Activity的状态,所以调用还是需要谨慎对待。

问题描述

最近公司的项目在Bug统计当中,发现了一大堆IllegalStateException的报错:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)    at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)    at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)    at android.view.View.performClick(View.java:4768)    at android.view.View$PerformClick.run(View.java:19692)    at android.os.Handler.handleCallback(Handler.java:739)    at android.os.Handler.dispatchMessage(Handler.java:95)    at android.os.Looper.loop(Looper.java:135)    at android.app.ActivityThread.main(ActivityThread.java:5539)    at java.lang.reflect.Method.invoke(Native Method)    at java.lang.reflect.Method.invoke(Method.java:372)    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

问题解决

在Activity已经保存了状态以后(onSaveInstanceState)进行了Fragment退栈操作(popBackStackImmediate),触发方法为调用了onBackPressed方法首先我们翻API 24的源码来看看onBackPressed里面到底都干啥了:

/** * Called when the activity has detected the user's press of the back * key.  The default implementation simply finishes the current activity, * but you can override this to do whatever you want. */public void onBackPressed() {    if (mActionBar != null && mActionBar.collapseActionView()) {        return;    }    if (!mFragments.getFragmentManager().popBackStackImmediate()) {        finishAfterTransition();    }}

果然,onBackPressed首先去关闭ActionBar的展开菜单(collapseActionView),其次再对FragmentManager进行退栈操作(popBackStackImmediate),最后才关闭Activity,低版本直接调用finish,高版本调用finishAfterTransition。而当Activity处于onSaveInstanceState状态之后时,调用onBackPressed报错,其实在Activity处于活动状态下时是没有任何问题的。个人习惯通常把Toolbar与onBackPressed方法捆绑起来:

/** * 设置Toolbar 为ActionBar * @param toolbarId Toolbar资源ID */public void setSupportActionBar(@IdRes int toolbarId) {    Toolbar mToolbar = (Toolbar) findViewById(toolbarId);    if (mToolbar != null) {        setSupportActionBar(mToolbar);        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                onNavigationClick();            }        });        getSupportActionBar().setDisplayShowTitleEnabled(false);    }}/** * Toolbar 返回按钮点击 */protected void onNavigationClick() {    onBackPressed();}

这里不存在问题,因为Toolbar的返回按钮必须得在Activity活动状态下才能点击到,而从代码层则需要通过遍历或者id找到到这个ImageButton再对其进行performClick操作(没有id,只能遍历),而真正问题出在于我将其写在网络请求结果处理的回调里面,毫无疑问,这就会出现Activity处于非活动状态了。

结论

  • 调用onBackPressed()方法需要注意Activity状态。
  • 调用onBackPressed()方法不一定就能结束Activity。
  • 调用onBackPressed()方法结束Activity,其调用的终究还是finish()方法。
0 0
原创粉丝点击