Android Activity生命周期一探究竟 及 主Activity里带Thread跳转时的注意事项

问题背景:

最近用到了主Activity里有一个Thread在处理数据,当跳转到第二个Activity时,希望Thread暂停。从第二个Activity回来时这个Thread再接着运行。今天得空顺着这个应用场景再过一下Activity的生命周期。

下面是一个小demo,主Activity里有个按钮,跳转到第二个Activity。在主Activity里有个UpdateThread在一直运行。第二个Activity里有个按钮,点击显示一个Dialog。下面是源码:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textview_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" 
        android:textSize="23dip"/>
    <Button 
        android:id="@+id/button_jump"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="跳转"
        android:textSize="23dip"/>

</RelativeLayout>

activity_second.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".SecondActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <Button
        android:id="@+id/button_show_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="显示Dialog"/>

</RelativeLayout>

MainActivity.java

package com.example.activitylife;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
	TextView mTextView = null;
	Button mBtutton = null;
	boolean allowRun = true;
	boolean allowUpdate = true;
	private static final String tag = "yan";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initUI();
		Log.i(tag, "onCreate...");
		mTextView.setText("..................." + "\n");
		mTextView.append("onCreate..." + "\n");
		new Thread(new UpdateThread()).start();
	}
	

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.i(tag, "onStart...");
		mTextView.append("onStart..." + "\n");
	}


	@Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
		Log.i(tag, "onRestart...");
		mTextView.append("onRestart..." + "\n");
	}


	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.i(tag, "onResume...");
		mTextView.append("onResume..." + "\n");
	}


	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.i(tag, "onPause...");
		mTextView.append("onPause..." + "\n");
	}


	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.i(tag, "onStop...");
	}


	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		Log.i(tag, "onDestroy...");
		super.onDestroy();
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	public void initUI(){
		mTextView = (TextView)findViewById(R.id.textview_show);
		mBtutton = (Button)findViewById(R.id.button_jump);
		mBtutton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//				allowRun = false;
//				allowUpdate = false;
				startActivity(intent);
			}
		});
	}
	class UpdateThread implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(allowRun){
				if(allowUpdate){
					try {
						Thread.sleep(1000);
						Log.i(tag, "UpdateThread....");
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			}
		}
		
	}
}

SecondActivity.java

package com.example.activitylife;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class SecondActivity extends Activity {
	private final static String tag = "yan";
	Button mShowDialogBtn = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);
	Log.i(tag, "SecondActivity:OnCreate...");
	mShowDialogBtn = (Button)findViewById(R.id.button_show_dialog);
	mShowDialogBtn.setOnClickListener(new View.OnClickListener() {
		
		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			showAlertDialog(SecondActivity.this);
		}
	});
	}

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.i(tag, "SecondActivity:onStart...");
	}

	@Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
		Log.i(tag, "SecondActivity:onRestart...");
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.i(tag, "SecondActivity:onResume...");
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.i(tag, "SecondActivity:onPause...");
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.i(tag, "SecondActivity:onStop...");
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.i(tag, "SecondActivity onDestroy...");
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.second, menu);
		return true;
	}
	
	public void showAlertDialog(Context c){
		Dialog dialog = new AlertDialog.Builder(c)
		.setTitle("通知")
		.setMessage("专注才能深入 ")
		.setIcon(android.R.drawable.ic_dialog_email)
		.setPositiveButton("确定", new OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				dialog.dismiss();
			}
		})
		.create();
		dialog.show();
	}

}
运行界面:





下面是得到的结论:

1、一个正常的Activity的流程:onCreate------onStart-----------onResume, onResume的时候就可以看到这个Activity,并跟这个Activity进行交互。之后如果正常退出的话,流程是:onPause--------onStop---------onDestroy.什么时候进行onPause的状态呢?在Activity不在是最前端,但依然可见时这个状态是onPause。所以切换到SecondActivity时,主Activity先进行onPause,当SecondActivity onResume可见时,主Activity进行onStop表示彻底不可见。 (正常的流程可简化记忆为:CS R, PS D. 有CS和PS打头  不会记混淆吧。)

2、如果不做特别处理,主Activity切换到SecondActivity后,只进行到onStop,如果自己写了finish(),那么从SecondActivity按返回键时就直接退出了,否则的话主Activity进行onRestart--------onStart-----onResume.恢复正常。

3、当主Activity里有个UpdateThread一直在运行时,即使切换到SecondActivity,它依旧没有被释放,并正常运行。

如果需要切换到第二个Activity时,UpdateThread停止运行,让allowUpdate = false。当切换回来时,让allowUpdate = true就ok了。

4、从SecondActivity按返回键时,SecondActivity自动进行了onDestroy.

5、如果不对主Activity做额外操作,当按返回键后,虽然他执行了onDestroy,但是UpdateThread一直在运行。这点比较奇葩,呵呵。所以要退出主程序时,一定让allowRun = false,确保Thread停止.

6、当在主Activity复写了OnBackPressed()时:

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		super.onBackPressed();
		MainActivity.this.finish();
	}
虽然finish()了,但是UpdateThread依旧在运行。

7、如果对主Activity进行锁屏,它从onResume-----切换到onPause---onStop的状态,不用说,UpdateThread依旧在运行。

8、当在SecondActivity按显示Dialog时,如上面第三幅图时,对SecondActivity的状态没有任何影响。这一点跟咱家之前的观念还不大一样,往后要更正了。其实可以这样理解,因为Dialog显示的时候,SecondActivity首先是可见的所以肯定不是onStop状态。再者,虽然SecondActivity貌似不在最前端了,但事实上他依旧可以合用户进行交互,在屏幕周围可以响应点击等事件。在本例中,如果不按Dialog的确定按键,而是点击屏幕其他区域一样可以让Dialog消失,所以SecondActivity没有进入onPause状态,而依旧是OnResume.

链接http://blog.csdn.net/lamp_zy/article/details/7703893说当按锁屏键时,原Activity只执行onPause而不执行onStop这是胡扯。此链接中还说,当有Dialog显示时,当前Activity会进入onPause状态而不进入OnStop状态,这亦是胡扯,真实情况是当有Dialog显示时,原Activity依旧是onResume状态。
这下Activity的生命周期终于真相大白了!!!

--------------------本文系原创,转载请注明作者:yanzi1225627


参考链接:

1、Dialog详解:http://blog.csdn.net/flyfight88/article/details/8602162

2、http://blog.csdn.net/hpoi/article/details/4629065

3、http://blog.csdn.net/hpoi/article/details/4629065

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。