您的位置:首页 > 其它

activity生命周期-进阶版(除了onCreate...onDestroy这些还有什么?)

2017-09-22 10:57 731 查看
时隔两年,我对于activity的生命周期非但未变得清晰,反而越来越疑惑。除了普通生命周期方法:onStart(),onRestart(),onCreate(),onResume(),onPause(),onStop(),onDestroy()这些,其实activity启动时,还有一些隐藏的,系统一定会调用的方法。

事实上,一些优秀的开源项目会重写这些方法,完成一些必要的操作,而我在看到这些方法,除了牛掰,大概看的懂之外,再无其他的感受了。

以下方法,也是系统一定会调用的方法:

onApplyThemeResource(Theme theme, int resid, boolean first)

onContentChanged()

onPostCreate()

onPostResume()

onAttachedToWindow()

onWindowFocusChanged(boolean hasFocus)

onDetachedFromWindow()

以下几个问题是一定要搞清楚的,为了我的生命周期大业:

这些方法和生命周期夹杂在一起,哪个先,哪个后?当对话框弹出来,会调用哪些?当应用进入后台,会调用哪些?

哪些获得的window是不为空的?

哪些进行数据处理,会对界面显示造成影响?(黑白屏,无焦点)

哪些可以对view进行初始化?

哪些可以获得控件的尺寸?

我想,这非常重要,此后还会特别关注view的生命周期。此次主要对以上问题进行测试,并进行结果记录。

1.执行顺序

启动执行顺序:(注意onPostCreate()未被调用)

onApplyThemeResource()

onContentChanged()

onCreate()

onStart()

onResume()

onPostResume()

onAttachedToWindow()

onWindowFocusChanged()

dialog弹出,关闭:

都只调用onWindowFocusChanged,额,onPause呢?难道7.0不用了?换个手机再试试。好吧,现在很多手机在dialog启动的时候不会onPause了,就调用了onWindowFocusChanged,看来课本什么的也不一定靠谱。或许有些型号依旧满足失去焦点会调用onPause,但我试的小米,红米都不会。

退出activity:

onPause()

onWindowFocusChanged()

onStop()

onDestroy()

onDetachedFromWindow()

注意,退出时onDetachedFromWindow()是在onDestroy()之后调用的。

转屏:

onPause()

onStop()

onDestroy()

onDetachedFromWindow()

onApplyThemeResource()

onContentChanged()

onCreate()

onStart()

onResume()

onPostResume()

onAttachedToWindow()

onWindowFocusChanged()

网上看到其他人测试会调用到onPostCreate(),但是我的真的没有,看来这个方法并不完全靠谱,决定弃疗。

2.哪些window不为空?

好吧,getWindow()都不为空,那么onAttachToWindow()的意义何在?试试getDecorView,终于有用了,测试结果:

onApplyThemeResource()DecorView@9f4f736[]

onContentChanged()DecorView@9f4f736[]

onCreate()DecorView@9f4f736[]

onStart()DecorView@9f4f736[]

onResume()DecorView@9f4f736[]

onPostResume()DecorView@9f4f736[]

onAttachedToWindow()DecorView@9f4f736[LifecycleActivity]

onWindowFocusChanged()DecorView@9f4f736[LifecycleActivity]

onPause()DecorView@9f4f736[LifecycleActivity]

onWindowFocusChanged()DecorView@9f4f736[LifecycleActivity]

onStop()DecorView@9f4f736[LifecycleActivity]

onDestroy()DecorView@9f4f736[LifecycleActivity]

onDetachedFromWindow()DecorView@9f4f736[LifecycleActivity]

发现了么?方括号里面的是DectorView绑定的activity,可以看到,这个DctorView确实挺特殊,从onAttatchToWindow以后就一直和activity处于绑定状态,包括onDestroy

当需要获取状态栏,标题栏高度的时候,可以用它,我记得应用要截屏的时候,也有用到,这时候注意放在onAttachedToWindow了。

状态栏,标题栏

Rect frame = new Rect();
  getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  int statusBarHeight = frame.top;
  Rect frame = new Rect();
  getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  int statusBarHeight = frame.top


屏幕截图:

public static Bitmap captureScreen(Activity activity) {

activity.getWindow().getDecorView().setDrawingCacheEnabled(true);

Bitmap bmp=activity.getWindow().getDecorView().getDrawingCache();

return bmp;

}


3.对于略耗时的操作,哪些对界面有影响哪些没有?

我这里指的略耗时,并不是像网络请求这种的,而是循环次数较多,数据略庞大,这里用:

for(int i = 0; i < 1000000; i++){
Log.e(TAG,"onPause()"+getWindow().getDecorView());
}


代替。

效果:

onStart()-黑屏卡死

onRestart()-卡死无黑屏

onResume()-黑屏卡死

onCreate()-黑屏卡死

onStop()-无影响

onPause()-黑屏卡死

onDestroy()-无影响

onApplyThemeResource()-黑屏卡死

onContentChanged()-黑屏卡死

onPostResume()-黑屏卡死

onAttachedToWindow()-黑屏卡死

onWindowFocusChanged()-无影响

onDetachedFromWindow()-无影响

可见启动过程中,唯一对于略多数据处理没有影响的就是onWindowFocusChanged(),关闭过程中,onStop(),onDestroy(),onDetachedFromWindow()无影响。让我略惊讶的是,onCreate方法中,进行这种处理也会卡死,如果这个数据降到100,对于卡死的方法效果会不同吗?

通过测试发现,其实那些卡死的在少量数据的情况下,或许会略卡顿,但是不会太明显,onCreate是一样的,卡顿效果略改善。所以对于少量数据处理,还是放在onCreate方法中更妥当一些。如果数据量略大,可考虑放在onAttachToWindow(),但是还有个问题,就是失去焦点时也会调用这个方法,需要添加一些条件判断。如果数据量庞大,还是放在异步中处理更妥善一些。

4.获取view,哪些为空?

onApplyThemeResource()null

onContentChanged()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onCreate()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onStart()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onResume()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onPostResume()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onAttachedToWindow()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-0,0 #7f0c0060 app:id/btn_lifecycle_dialog}

onWindowFocusChanged()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……I. 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

onPause()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. …….. 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

onWindowFocusChanged()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. …….. 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

onStop()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. …….. 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

onDestroy()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. …….. 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

onDetachedFromWindow()android.support.v7.widget.AppCompatButton{227e6023 VFED..C. ……ID 0,0-600,240 #7f0c0060 app:id/btn_lifecycle_dialog}

可以看到,除了onApplyThemeResource都可以获取到view,不过应该不是每个都能对view进行操作吧,试试setText(),结果是,真的都可以!

5.控件尺寸:

当然onApplyThemeResource因为获得view为null不可以,就不试了,我这里简单粗暴,直接getWidth()获取控件宽度。

onContentChanged()0

nCreate()0

onStart()0

onResume()0

onPostResume()0

onAttachedToWindow()0

onWindowFocusChanged()600

onPause()600

onWindowFocusChanged()600

onStop()600

onDestroy()600

onDetachedFromWindow()600

可以看到,onWindowFocusChanged是创建过程中唯一可以获得正确的尺寸的。

总结

所实话,这次测试受益很大,尤其是dialog弹出那里,原来有些手机除了销毁已经不怎么用onPause了,这个方法既然在有的手机内不能作为失去焦点的依据,那么以后就要把onWindowFocusChanged(false)当做onPause用了。

说几点关键的:

onAttachedToWindow()-decorView开始不为空,可用于获取状态栏高度等,以后重写后我要把它变成onAttachedDecorView(),便于理解。

onWindowFocusChanged-true可以用来获取尺寸,以及略多的数据初始化,false可以当onPause用

onStart/onResume/onRestart这些还是不要随便用,可以用onWindowFocusChanged(true)代替,这个方
bb89
法可以处理稍大些的数据,用户体验应该较好。重写时会将true的时候分到onStartDataDimen(),false时分到onPauseDataDimen(),容易记忆。

因为每次打开界面(包括打开dialog)onWindowFocusChanged,home键都会被调用,还可以用于作用于数据保存和恢复,放在intent里面就可以了:

@Override
public void onWindowFocusChanged(boolean hasFocus) {//可以
super.onWindowFocusChanged(hasFocus);
Log.e(TAG,"onWindowFocusChanged()"+getIntent()+num);
if(hasFocus) {
num = getIntent().getIntExtra("num", 0);
boolean isFirst = getIntent().getBooleanExtra("isFirst",true);
if(isFirst){
num = 5;
getIntent().putExtra("isFirst",false);
}

}else
getIntent().putExtra("num",num);
}


这部分可以放到onCreate():

boolean isFirst = getIntent().getBooleanExtra("isFirst",true);
if(isFirst){
num = 5;
getIntent().putExtra("isFirst",false);
}


比onCreate+onSaveInstance靠谱多了,哈哈,这个方法好万能啊,还不会卡顿。

ps:以前都是用post获取的宽高,自定义组件多了白屏就延时加载,呵呵,测过之后被自己蠢哭了T T.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: