复习Android,Activity的生命周期——个人总结归纳

启动或结束一个Activity,我们就要跟它的生命周期打交道,安卓程序猿根据Activity的生命周期中各回调方法的触发时机处理对应的业务逻辑,以保证用户与页面之间能正常良好地交互。



这张图片多少人已经看烂了,不过我们依旧拿来参考Activity的生命周期。

新建一个Activity名为LifeCycleActivity。这是Activity的XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <EditText
        android:id="@+id/m_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="90dp"
        android:layout_marginBottom="30dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:textSize="16sp"
        android:ems="10" />

    <Button
        android:id="@+id/m_btnext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="跳转LifeJumpActivity" />

</LinearLayout>
然后是JAVA代码

public class LifeCycleActivity extends Activity {

	private EditText medit;
	private String s_txt;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.e("LifeCycleActivity-", "onCreate");
		setContentView(R.layout.activity_lifecycle);
		medit = (EditText) findViewById(R.id.m_edittext);
		findViewById(R.id.m_btnext).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Intent ite = new Intent(LifeCycleActivity.this, LifeJumpActivity.class);
				startActivity(ite);
			}
		});
	}
	
	//是否按了键盘返回键
	@Override
	public void onBackPressed() {
		Log.e("LifeCycleActivity-", "onBackPressed");
		super.onBackPressed();
	}
	
	@Override
	protected void onDestroy() {
		Log.e("LifeCycleActivity-", "onDestroy");
		super.onDestroy();
	}
	
	@Override
	public void onLowMemory() {
		Log.e("LifeCycleActivity-", "onLowMemory");
		super.onLowMemory();
	}
	
	@Override
	public void onTrimMemory(int level) {
		Log.e("LifeCycleActivity-", "onTrimMemory");
		super.onTrimMemory(level);
		Log.e("onTrimMemory-", "level:"+level);
		switch(level) {
		case TRIM_MEMORY_COMPLETE:
			Log.e("onTrimMemory-", "内存不足,并且该进程在后台进程列表最后一个,马上就要被清理");
			break;
		case TRIM_MEMORY_MODERATE:
			Log.e("onTrimMemory-", "内存不足,并且该进程在后台进程列表的中部");
			break;
		case TRIM_MEMORY_BACKGROUND:
			Log.e("onTrimMemory-", "内存不足,并且该进程是后台进程");
			break;
		case TRIM_MEMORY_UI_HIDDEN:
			Log.e("onTrimMemory-", "内存不足,并且该进程的UI已经不可见了");
			break;
		case TRIM_MEMORY_RUNNING_CRITICAL:
			Log.e("onTrimMemory-", "内存不足(后台进程不足3个),并且该进程优先级比较高,需要清理内存");
			break;
		case TRIM_MEMORY_RUNNING_LOW:
			Log.e("onTrimMemory-", "内存不足(后台进程不足5个),并且该进程优先级比较高,需要清理内存");
			break;
		case TRIM_MEMORY_RUNNING_MODERATE:
			Log.e("onTrimMemory-", "内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存");
			break;
		}
	}
	
	@Override
	protected void onPause() {
		Log.e("LifeCycleActivity-", "onPause");
		super.onPause();
		s_txt = medit.getText().toString();
	}
	
	@Override
	protected void onRestart() {
		Log.e("LifeCycleActivity-", "onRestart");
		super.onRestart();
	}
	
	@Override
	protected void onResume() {
		Log.e("LifeCycleActivity-", "onResume");
		super.onResume();
		medit.setText(s_txt);
	}
	
	/*onPostResume出现在onResume后,实际开发应用*/
	/*@Override
	protected void onPostResume() {
		Log.e("LifeCycleActivity-", "onPostResume");
		super.onPostResume();
	}*/
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		Log.e("LifeCycleActivity-", "onRestoreInstanceState");
		super.onRestoreInstanceState(savedInstanceState);
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		Log.e("LifeCycleActivity-", "onSaveInstanceState");
		super.onSaveInstanceState(outState);
	}
	
	@Override
	protected void onStart() {
		Log.e("LifeCycleActivity-", "onStart");
		super.onStart();
	}
	
	@Override
	protected void onStop() {
		Log.e("LifeCycleActivity-", "onStop");
		super.onStop();
	}
	
	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		Log.e("LifeCycleActivity-", "onWindowFocusChanged");
//		Log.e("LifeCycleActivity-", "onWindowFocusChanged-hasFocus:"+hasFocus);
		super.onWindowFocusChanged(hasFocus);
	}
	
	/*屏幕的Activity加监听屏幕属性改变,发生改变则检查当前是否全屏状态。是全屏状态发送,全屏的广播消息,到监听应用触发操作。
	 *注意该判断在屏幕切换横竖屏是也会触发,需要根据实际情况过滤横竖屏切换的情况。*/
	@Override
	public void onWindowAttributesChanged(LayoutParams params) {
		Log.e("LifeCycleActivity-", "onWindowAttributesChanged");
		super.onWindowAttributesChanged(params);
		if (WindowManager.LayoutParams.FLAG_FULLSCREEN == getWindow().getAttributes().flags) {
            Log.e("LifeCycleActivity-","onWindowAttributesChanged()-FLAG_FULLSCREEN");
        }
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		Log.e("LifeCycleActivity-", "onConfigurationChanged");
		super.onConfigurationChanged(newConfig);
	}
	
}


运行示例的代码在真机上,各个生命周期的过程如下:

1,Activity创建到显示:onCreate,onWindowAttributesChanged,onStart,onResume,onWindowFocusChanged
2,Activity从显示到关闭:onBackPressed(按下手机返回键),onPause,onWindowFocusChanged,onStop,onDestroy

3,显示的Activity按下home键:onPause,onWindowFocusChanged,onTrimMemory,onSaveInstanceState,onStop

4,按下home后再次回到此Activity:onRestart,onStart,onResume,onWindowFocusChanged

5,Activity里定义了一个EditText,用户按下了home键,Activity进入后台不可见,如果已经输入过文字,用户返回此Activity时希望EditText能显示输入的文字,此时就需要保存和读取文字。保存EditText的文字可以在onSaveInstanceState和onPause里保存,返回此Activity里时可以在onRestart,onStart,onResume里显示保存的文字,这里使用的是onPause保存,onResume显示,因为从前面可以看到Activity调用onPause和onResume较为普遍,当然你可以选择其他的时态,只要结果一样就行。

6,从此Activity跳转到新的Activity时:onPause,onWindowFocusChanged,onSaveInstanceState,onStop;
  从新的Activity返回此Activity时:onRestart,onStart,onResume,onWindowFocusChanged

7,当Activity处于被覆盖或后台不可见状态,系统内存不足而干掉此Activity,而后用户返回了此Activity:
onCreate,onWindowAttributesChanged,onStart,onResume,onWindowFocusChanged

以上7种是比较常见的生命周期过程,接下来再讲一下各个时态方法调用的时机。

onCreate:Activity创建时被调用

onStart:Activity创建或者从后台重新回到前台时被调用

onRestart:Activity从后台重新回到前台时被调用

onResume:Activity创建或者从被覆盖、后台重新回到前台时被调用

onPostResume:出现在onResume后,实际开发应用较少

onPause:Activity被覆盖到下面或者锁屏时被调用

onStop:退出当前Activity或者跳转到新Activity时被调用

onDestroy:退出当前Activity时被调用,调用之后Activity就结束了

onWindowFocusChanged:Activity窗口获得或失去焦点时被调用,在onResume或onPause之后

onSaveInstanceState:Activity被系统杀死时被调用,例如:屏幕方向改变时,Activity被销毁再重建;

当前Activity处于后台,系统资源紧张将其杀死。另外,当跳转到其他Activity或者按Home键回到主屏时

该方法也会被调用,系统是为了保存当前View组件的状态。它在onPause之后被调用。

onRestoreInstanceState:Activity被系统杀死后再重建时被调用,例如:屏幕方向改变时,Activity被销毁再重建;当前Activity处于后台,系统资源紧张将其杀死,用户又启动该Activity。这两种情况下onRestoreInstanceState都会被调用,它的调用时机在onStart之后。

onWindowAttributesChanged:监听屏幕状态是否改变,检查当前屏幕是否全屏。Activity切换横竖屏时也会调用这个方法。


*** onLowMemory和onTrimMemory系统内存优化方法

当某个Activity处于后台不可见状态时,如果它带有较多Bitmap、数组、控件等占用内存较大的资源,此时在onLowMemory或onTrimMemory方法中重写方法来释放占用过多的内存。稍微注意以下几点:

1,OnLowMemory被回调时,已经没有后台进程;而onTrimMemory被回调时,还有后台进程。
2,OnLowMemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;而OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
3,通过一键清理后,OnLowMemory不会被触发,而OnTrimMemory会被触发一次。

具体又兴趣可以参考以下两篇文章:

应用内存优化之OnLowMemory&OnTrimMemory    点击打开链接

应用内存优化之OnLowMemory&OnTrimMemory    点击打开链接


*** Activity横竖切换屏幕生命周期

新建一个Activity,名为LifeJumpActivity,代码与LifeCycleActivity,只是多了重写监听屏幕横竖屏切换的方法onConfigurationChanged,下面是代码:

@Override
	public void onConfigurationChanged(Configuration newConfig) {
		Log.e("LifeJumpActivity-", "onConfigurationChanged");
		super.onConfigurationChanged(newConfig);
		switch (newConfig.orientation) {  
        case Configuration.ORIENTATION_PORTRAIT:
        	LifeJumpActivity.this.setContentView(R.layout.orientation_portrait);
            Log.e("onConfigurationChanged", "切换到竖屏");
            break;  
        case Configuration.ORIENTATION_LANDSCAPE:
        	LifeJumpActivity.this.setContentView(R.layout.orientation_landscape);
        	Log.e("onConfigurationChanged", "切换到横屏");
            break;  
        }
	}

可以看到,切换竖屏时重设布局orientation_portrait,切换横屏时则为orientation_landscape。

当次Activity并未在AndroidManifest.xml配置 android:configChanges="screenSize|orientation"时,Activity切换横竖屏时是会调用到生命周期的。

1,当Activity切换横竖屏时都会调用到如下生命周期:onPause,onSaveInstanceState,onStop,onDestroy,onCreate,onWindowAttributesChanged,onStart,onRestoreInstanceState,onResume,onWindowFocusChanged;而且此时setContentView方法无效。

2,当给此Activity添加了 android:configChanges="screenSize|orientation"属性后,Activity自动捕捉到设备屏幕方向和大小的改变,此时Activity只调用了onConfigurationChanged方法,而setContentView此时有效。注意Android4.0以后要使Activity切换横竖屏时不改变生命周期,必须为screenSize|orientation。

但是要注意,如果给Activity配置了android:screenOrientation属性,就会使android:configChanges设置的属性失效。


以上就是我复习总结的Activity生命周期,如有错误,敬请指正!


demo下载地址


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值