现在的位置: 首页 > 综合 > 正文

(2)Managing the Activity Lifecycle

2017年12月24日 ⁄ 综合 ⁄ 共 13120字 ⁄ 字号 评论关闭

Starting an Activity


 A simplified illustration of the Activity lifecycle, expressed as a step pyramid. This shows how, for every callback
used to take the activity a step toward the Resumed state at the top, there's a callback method that takes the activity a step down. The activity can also return to the resumed state from the Paused and Stopped state.

 However, only three of these states can be static. That is, the
activity can exist in one of only three states for an extended period of time:

Resumed
In this state, the activity is in the foreground and the user can interact with it.
Paused
In this state, the activity is partially obscured by another activity—the other activity that's in the foreground is semi-transparent or doesn't cover the entire screen. The paused activity
does not receive user input and cannot execute any code.
Stopped

In this state, the activity is completely hidden and not visible to the user; it is considered to be in the background. While stopped, the activity instance and all its state information such as member variables is retained, but it cannot execute any code.

The other states (Created and Started) are transient and the system quickly moves from them to the next state by calling the next lifecycle callback method. That is, after the system calls onCreate(),
it quickly callsonStart(), which is quickly followed by onResume().

<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>

When
the user selects your app icon from the Home screen, the system calls the 
onCreate() method
for the
Activity in your app that you've declared to be the "launcher" (or "main")
activity. This is the activity that serves as the main entry point to your app's user interface.

If
either the 
MAIN action or LAUNCHER category
are not declared for one of your activities, then your app icon will not appear in the Home screen's list of apps.

TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    // 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);
    }
}

Using the SDK_INT to
prevent older system's from executing new APIs works in this way on Android 2.0 (API level 5) and higher only. Older versions will encounter a runtime exception.


 Another illustration of the activity lifecycle structure with an emphasis on the three main callbacks that the system
calls in sequence when creating a new instance of the activity: 
onCreate()onStart(),
and 
onResume(). Once this sequence of callbacks complete, the activity
reaches the Resumed state where users can interact with the activity until they switch to a different activity.

While the activity's first lifecycle callback is onCreate(), its very
last callback is onDestroy(). The system calls this method on your activity as the final signal that your activity instance is being completely removed from the system memory.

However, if your activity
includes background threads that you created during 
onCreate() or
other long-running resources that could potentially leak memory if not properly closed, you should kill them during 
onDestroy().

 The
system calls 
onDestroy() after it has already called onPause() and onStop() in
all situations except one: when you call 
finish() from within the onCreate() method.

Pausing and Resuming an Activity

    During normal app use, the foreground activity is sometimes obstructed by other visual components that cause the activity to pause. For example, when a semi-transparent activity opens (such as one in the style of a dialog), the previous activity pauses.
As long as the activity is still partially visible but currently not the activity in focus, it remains paused.

However, once the activity is fully-obstructed and not visible, itstops 

 When a semi-transparent activity obscures your activity, the system calls onPause() and
the activity waits in the Paused state (1). If the user returns to the activity while it's still paused, the system calls 
onResume() (2).

When the system calls onPause() for your activity, it technically means your activity is still partially visible, but most often is an indication that the user is leaving
the activity and it will soon enter the Stopped state. You should usually use the onPause() callback to:

  • Stop animations or other ongoing actions that could consume CPU.
  • Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
  • Release system resources, such as broadcast receivers, handles to sensors (like GPS), or any resources that may affect battery life while your activity is paused and the user does not need them.
@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;
    }
}

Generally, you should not use onPause() to store user changes (such as personal information entered into a form) to permanent storage. The only time you should persist
user changes to permanent storage withinonPause() is when you're certain users expect the changes to be auto-saved (such as when drafting an email). However, you should
avoid performing CPU-intensive work during onPause(), such as writing to a database, because it can slow the visible transition to the next activity (you should instead
perform heavy-load shutdown operations during onStop()).

You should keep the amount of operations done in the onPause() method relatively simple in order to allow for a speedy transition to the user's next destination if your
activity is actually being stopped.

When your activity is paused, the Activity instance
is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state.

Be aware that the system calls this method every time your activity comes into the foreground, including when it's created for the first time.

@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
    }
}

Stopping and Restarting an Activity

a few of key scenarios in which your activity is stopped and restarted:

The user opens the Recent Apps window and switches from your app to another app.

The user performs an action in your app that starts a new activity.

The user receives a
phone call while using your app 

Because the system retains your Activity instance
in system memory when it is stopped, it's possible that you don't need to implement the 
onStop() and onRestart() (or
even 
onStart() methods at all. For most activities that are relatively
simple, the activity will stop and restart just fine and you might only need to use 
onPause() to
pause ongoing actions and disconnect from system resources.


 When
the user leaves your activity, the system calls 
onStop() to stop the activity
(1). If the user returns while the activity is stopped, the system calls 
onRestart() (2),
quickly followed by 
onStart() (3) and onResume() (4).
Notice that no matter what scenario causes the activity to stop, the system always calls 
onPause() before
calling
onStop().

it's
important you use 
onStop() to release resources that might leak memory.

Although
the 
onPause() method is called before onStop(),
you should use 
onStop() to perform larger, more CPU intensive shut-down
operations, such as writing information to a database.

@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.
            );
}

When your activity is stopped, the Activity object
is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state. The system also keeps track of the current state for each 
View in
the layout, so if the user entered text into an 
EditText widget, that content
is retained so you don't need to save and restore it.

Even
if the system destroys your activity while it's stopped, it still retains the state of the 
View objects
(such as text in an 
EditText) in a Bundle (a
blob of key-value pairs) and restores them if the user navigates back to the same instance of the activity.

It's
uncommon that an app needs to use 
onRestart() to restore the activity's
state, so there aren't any guidelines for this method that apply to the general population of apps.

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    
}

onDestroy(),This method is your last chance to clean out resources that could lead to a memory leak, so you should be sure that additional threads are destroyed and
other long-running actions like method tracing are also stopped.

Recreating an Activity

When your activity is destroyed because the user presses Backor
the activity finishes itself, the system's concept of that
Activity instance is gone
forever because the behavior indicates the activity is no longer needed. However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual 
Activity instance
is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system
uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a 
Bundle object.

Your activity will be destroyed and recreated each time the user rotates
the screen. 

By default, the system
uses the 
Bundle instance state to save information about each View object
in your activity layout (such as the text value entered into an 
EditText object).
So, if your activity instance is destroyed and recreated, the state of the layout is restored to its previous state with no code required by you. However, your activity might have more state information that you'd like to restore, such as member variables
that track the user's progress in the activity.

In
order for the Android system to restore the state of the views in your activity, 
each view must have a unique ID, supplied by the android:id attribute.

To
save additional data about the activity state, you must override the 
onSaveInstanceState() callback
method. The system calls this method when the user is leaving your activity and passes it the 
Bundle object
that will be saved in the event that your activity is destroyed unexpectedly. If the system must recreate the activity instance later, it passes the same 
Bundle object
to both the 
onRestoreInstanceState() andonCreate() methods.


As
the system begins to stop your activity, it calls 
onSaveInstanceState() (1)
so you can specify additional state data you'd like to save in case the 
Activity instance
must be recreated. If the activity is destroyed and the same instance must be recreated, the system passes the state data defined at (1) to both the 
onCreate() method
(2) and the
onRestoreInstanceState() method
(3).

The default implementation of this method saves information about the state of the activity's view hierarchy, such as the text in an EditText widget or the scroll position of
aListView.

To save additional state information for your activity, you must implement onSaveInstanceState() and add key-value pairs to the Bundle object. 

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

you must check whether the state Bundle is
null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first
   
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need
to check whether the Bundle is null:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
   
    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

抱歉!评论已关闭.