Android Activity生命周期一探究竟 及 主Activity裡帶Thread跳轉時的註意事項

問題背景:

最近用到瞭主Activity裡有一個Thread在處理數據,當跳轉到第二個Activity時,希望Thread暫停。從第二個Activity回來時這個Thread再接著運行。今天得空順著這個應用場景再過一下Activity的生命周期。

下面是一個小demo,主Activity裡有個按鈕,跳轉到第二個Activity。在主Activity裡有個UpdateThread在一直運行。第二個Activity裡有個按鈕,點擊顯示一個Dialog。下面是源碼:

activity_main.xml


    
    

activity_second.xml


    
    

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不在是最前端,但依然可見時這個狀態是onPausevc3Ryb25nPqGjy/nS1MfQu7u1vVNlY29uZEFjdGl2aXR5yrGjrNb3QWN0aXZpdHnPyL340NBvblBhdXNlo6y1sVNlY29uZEFjdGl2aXR5IG9uUmVzdW1lv8m8+8qxo6zW90FjdGl2aXR5vfjQ0DxzdHJvbmc+b25TdG9wPC9zdHJvbmc+o6w8c3Ryb25nPrHtyr6zubXXsru/ybz7PC9zdHJvbmc+oaMgKNX9s6O1xMH3s8y/ybzyu6+8x9Lkzqo8c3Ryb25nPjpDUyBSLCBQUyBEPC9zdHJvbmc+LiDT0ENTus1QU7TyzbcgILK7u+G8x7vsz/2wyaGjPGltZyBhbHQ9″大笑” src=”/uploadfile/Collfiles/20140225/20140225085420258.gif” />)

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.

鏈接https://blog.csdn.net/lamp_zy/article/details/7703893說當按鎖屏鍵時,原Activity隻執行onPause而不執行onStop這是胡扯。此鏈接中還說,當有Dialog顯示時,當前Activity會進入onPause狀態而不進入OnStop狀態,這亦是胡扯,真實情況是當有Dialog顯示時,原Activity依舊是onResume狀態。
這下Activity的生命周期終於真相大白瞭!!!偷笑奮鬥

——————–本文系原創,轉載請註明作者:yanzi1225627

參考鏈接:

1、Dialog詳解:https://blog.csdn.net/flyfight88/article/details/8602162

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

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

發佈留言