【Android开发】管理Activity的生命周期(1)

在使用用户导航打开、退出和返回到自己设计的App时,App的Acitivity实例在它们的生命周期进行不同的状态转换。

例如,当第一次打开一个Activity时,则显示在系统的屏幕,在这个过程中,Android系统调用了一系列的生命周期方法,若用户执行一个动作打开另一个activity或转换到另一个App,系统调用另外一些的生命周期方法让App转入后台(此时Activity不可见,但其实例和状态保持完整的)。


在生命周期回调方法中,当用户退出和重新进入Activity时,可以自己声明Activity的行为。例如,若要构建一个流视频播放器,当用户转换到另一个App时,则要停止视频和终止网络连接。当用户返回时,则重新连接网络和允许用户从原来的地点恢复视频。


接下来学习一下各个Activity实例接受的各种重要的生命周期回调方法和如何使用它们,以实现用户期望Activity的行为。当Activity不需要系统资源时,应该不要消耗它们。


一、开启一个Activity


不像其他的编程实例,App从main()方法启动。在Android系统中,通过调用指定的对应指定的生命周期阶段的回调函数来初始化一个Activity实例。在Android系统中,有一系列的回调函数用于启动一个Activity,以及一些列的用于销毁一个Activity的回调函数。


1.理解生命周期回调

在一个Activity的生命中,系统调用一系列核心的生命周期方法以类似步骤金字塔的顺序,如下图所示,


就是说,Activity生命周期的各个阶段在金字塔上是一个单独的步骤。随着系统创建一个新的Activity实例,各个回调方法从一步一步转换Activity状态。金字塔的顶端是Activity正运行在前台的点,此时可以和用户交互。


随着用户退出Activity,系统调用其他的方法,转换Activity状态直到退到金字塔的底部,以销毁Activity。在一些情况中,Activity只转换部分步骤直到金字塔的某个位置,然后等待(例如,当用户转到其他的App时),此处,该Activity还是可以从中止的点恢复的(例如,返回到该activity)。


在实际应用中,要依据Activity的复杂性来决定使用哪些生命周期方法,有可能不需要实现所有的生命周期方法。然而,作为开发人员,理解各个方法的使用和实现,对于确保App的行为满足自己的需求是非常重要的。实现Activity的这些生命周期方法可以确保App在某些方面行为是正确的,例如:

  • 当正在使用App时,用户接听电话或转到其他的App,不会发生碰撞
  • 当用户不在主要使用App时不会消耗有价值的系统资源
  • 当退出App,后续再打开时不会丢失用户的进度
  • 当用户在横向和纵向转换时,不会发生碰撞或丢失用户进度
在上面的图中的所有状态中,只有三个状态是静止的。就是说,Activity能在这三个状态之一是存在一段扩展的时间。
Resumed:
在该状态,Activity是在前台,用户可以和它进行交互,(有时,也涉及作为“运行”状态)

Paused:
在该状态,Activity部分被另一个Activity掩盖——即其他在前台的Activity是半透明的或没有完全覆盖整个屏幕。Paused Activity不能接受用户的输入和不能执行任何代码。

Stopped:
在该状态,Activity是完全隐藏的,对用户是不可见的,可以认为是在后台。当处于stopped状态时,activity实例和它的所有状态信息(像成员变量)都保留的,但是不能执行任何代码。

其他的状态(Created和Started)是瞬变的,系统快速的从这些状态转移到下一个状态(通过调用下一个生命周期回调方法),即系统调用onCreate()后,快速的调用onStart(),接着快速的调用onResume()。

以上就是基本的Activity生命周期。

2.指定App的Launcher Activity
当用户从Home屏幕选择App图片时,系统为该App的Activity调用onCreate(), 即声明为将“Launcher ”(或“main”) Activity。该Activity即是作为App用户界面的进入点。

在Android manifest file文件AndroidManifest.xml中需要定义哪一个activity用作Launcher activity。

App的Launcher Activity必须通过<intent-filter>来声明,其中包括MAIN动作和LAUNCHER类别,例如:
<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
注:当使用Android SDK工具创建一个新的Android工程时,包含Activity类的缺省工程文件中已默认声明了。

若MAIN action或LAUNCHER category有一个没有声明时,App图片将不会出现在Home屏幕的应用列表中。

3.创建一个新的实例
大多数的App包含多个不同的Activities,允许用户指定不同的动作,不管是用户点击App图标创建的Activity还是App相应用户动作开启的另一个不同的Activity。系统都通过调用它的onCreate()方法来创建每一个新的Activity实例。

在开发App时,必须实现onCreate()方法来执行基本的应用启动逻辑,对于Activity的整个生命来说,onCreate()只在启动时执行一次。例如,onCreate()的实现应该定义用户接口和可能实例化一些域变量。

例如,对于下列的onCreate()例子,对于activity来说,执行一个基本的设置,像声明用户界面(定义的XML布局文件),定义成员变量和配置一些UI。
TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set the user interface layout for this Activity
    // The layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);
    
    // Initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_message);
    
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}
注意:使用SDK_INT方法老版本系统执行新的API(Android 2.0或更高),老版本将会遇到运行时异常。

一旦onCreate()执行完成,系统接着马上就调用onStart()和onResume()方法。Activity从来不会驻留在Created或Started状态。技术上,当onStart()被调用时,activity对于用户来说就是可见的,但是onResume()快速的跟着就执行,Activity保持在Resumed状态直到有时间触发改变该状态,像接到一个电话,用户切换到另一个Activity,或设备屏幕关闭。

其他的启动方法,onStart和onResume(),当用于从Paused或Stopped状态恢复时,是非常有用的。

注:在onCreate()方法中包括称为savedInstanceState的参数将在后续讨论。

4.销毁Activity
Activity的第一个生命周期回调是onCreate(),最后一个回调函数时onDestroy(), 当Activity接受到Activity实例被完全从系统内存中消除的信号时,将调用该函数。

大多数的App不需要执行该方法,因为局部的类引用被Activity销毁,activity在onPause()和onStop()期间执行大多数的清理工作。然而,若Activity在onCreate()期间创建了一个后台线程或其他长期运行的资源存在潜在的内存泄漏没有合理的关闭,就应该使用onDestroy()。
@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass
    
    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}
注:在所有的情况下(除了如下情况:在onCreate()方法中调用finish()),当已经调用了onPause()和onStop()后,系统将会调用onDestroy。
在一些情况,像当Activity暂时的启动另一个activity,就有可能会从onCreate()中调用finish()来销毁activity,在这种情况下,系统立即调用onDestroy()而不用调用其他任何类型的生命周期方法

二、暂停和恢复一个Activity

在正常的使用App时,前台的Activity有时会被其他可见的组件阻塞,导致该Activity暂停,例如,当打开一个半透明的activity(像对话框),则前一个Activity暂停,只要该Activity仍然是部分可见的,则其就保持为Paused状态。

然而,一旦该Activity被全阻塞和不可见,则停止。

当Activity进入paused状态是,在Activity中调用onPause()方法,其允许停止正在执行的动作(像视频),在用户保留App的情况下,应永久保存任何信息,若用户从paused状态返回到activity时,系统恢复保存的信息,调用onResume()方法。

注:当Activity收到一个onPause()调用时,表示activity将会暂停一会。

整个onPause()和onResume()的状态转换图如下:

1.暂停一个Activity
当系统调用onPause()时,技术上意味着activity仍然部分可见,但是大多数情况下表示用户正在退出该activity,该activity将进入Stopped状态,应该对如下情况使用onPause():
  • 停止动画或其他正在进行的动作,这些消耗CPU
  • 提交不保存的改变,但是当用户离开时,用户期望这样的改变被保存时(像draft email)
  • 释放系统资源,像broadcast receivers,处理传感器(像GPS)或其他任何影响电池寿命的资源(当activity处于暂停状态或用户不需要它们时)。
例如,当App中使用Camera,onPause是一个释放它的好地方,如下:
@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release()
        mCamera = null;
    }
}
通常,不应该使用onPause()来存储用户改变(像个人信息)到永久存储器中,通过onPause()存储改变到永久存储器仅仅在确保用户期望改变被自动存储(像存储email草稿件)。然而,在执行onPause()期间,应该避免执行CPU的过度工作,像写数据库等,因为这将减慢可视的转换到下一个activity(应该在onStop()调用时,执行过度的关闭操作)。

在onPause()调用期间,应该保持操作的相对简单,为了快速的转换到用户的下一个activity。


2.恢复一个Activity
当用户从Paused状态恢复时,系统调用onResume()方法。

应注意到,每次activity回到前台之前时,系统都要调用该方法。包括第一次创建该Activity。为此,在onResume()中应该实现初始化在onPause()中释放的组件,以及其他的进入Resumed状态时必须的初始化操作(像开始动画和使用的组件)。

下面的例子是上面onPause的对应例子。所以它初始化了camera(onPause()中释放的camera)
@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}

三、停止和重启一个Activity

合理的停止和重启activity在activity的生命周期中是非常重要的过程,以确保用户察觉到App一直是存在着的,没有丢失它的进度。以下介绍一些关键的场景,其中activity被停止和重启:
  • 用户打开最近的App窗口,从一个App转到另一个App。App中在前台运行的activity被停止。若用户从Home屏幕启动图标的App或最近的App窗口恢复,则activity重启。
  • 用户在App中执行启动另一个activity的工作。则当第二个activity被创建时,当前的activity被停止,然后若用户按下Back按钮,则第一个activity重启。
  • 当使用App过程中接听电话。

Activity类提供了两个生命周期方法,onStop()和onRestart()。该函数允许指定activity被停止和重启。不像其他的Paused状态,其通过识别部分UI阻塞,Stopped状态确保UI可见,用户的焦点在一个单独的activty(或整个的单独App)。

 

1.停止一个activity

当Activity接收onStop()方法调用时,则其不再可见,将释放所用用户不使用的和不需要的资源。一旦activity停止,系统若需要则将销毁实例以恢复系统该内存,在极端情况下,系统可能会简单的在没有Activity的onDestroy()回调函数的情况下杀死App进程。所以,用onStop()来释放资源以免造成内存泄露是非常重要的。

 

关键在onStop()之前会调用onPause()方法,但应该使用onStop()进行更大的、更彻底的关闭操作,以释放资源,像写信息到数据库。

 

例如,以下是onStop()的实现保存临时存储的内容到永久存储器中:

 

@Override 
protected void onStop() {     
	super.onStop();  // Always call the superclass method first      
	
	// Save the note's current draft, because the activity is stopping     
	// and we want to be sure the current note progress isn't lost.     
	ContentValues values = new ContentValues();     
	values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());     
	values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());      
	
	getContentResolver().update(             
			mUri,    // The URI for the note to update.             
			values,  // The map of column names and new values to apply to them.             
			null,    // No SELECT criteria are used.             
			null     // No WHERE columns are used.             
	); 
}


2.开启/重启一个Activity

实例如下:

@Override 
protected void onStart() {     
	super.onStart();  // Always call the superclass method first   
	
	// The activity is either being restarted or started for the first time     
	// so this is where we should make sure that GPS is enabled     
	LocationManager locationManager =              
			(LocationManager) getSystemService(Context.LOCATION_SERVICE);     
	boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);          
	if (!gpsEnabled) {         
		// Create a dialog here that requests the user to enable GPS, and use an intent         
		// with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action         
		// to take the user to the Settings screen to enable GPS when they click "OK"     
	}
}  

@Override 
protected void onRestart() {     
	super.onRestart();  // Always call the superclass method first          
	// Activity being restarted from stopped state     
}

 

四、重新创建一个Activity



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值