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