在使用用户导航打开、退出和返回到自己设计的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在某些方面行为是正确的,例如:
<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类的缺省工程文件中已默认声明了。
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或更高),老版本将会遇到运行时异常。
@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。
@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()调用时,执行过度的关闭操作)。
@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类提供了两个生命周期方法,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