Ch 3: Applications, Activities and Fragments Flashcards
Major Building Blocks
of
Android Applications
- Activities
- Services
- Intents
- Broadcast Receivers
- Content Providers
- Notifications
Application Components:
Activities Overview
The presentation layer of an Application.
The UI is built around one or more extensions of the Activity class.
Activities use Fragments and Views to lay out and display information, and to respond to user actions.
Application Components:
Services Overview
Service components run without a UI.
Used to perform long-running tasks, or tasks that require no user interaction (such as tasks that continue when Activities are not active or visible)
Common uses:
- updating data sources
- triggering Notifications
- broadcasting Intents
Application Components:
Intents Overview
A powerful inter-application message-passing framework.
Used extensively throughout Android.
Types:
- Explicit
- Implicit
- Broadcast
Uses:
- Start and Stop Activities and Services
- Broadcast messages system-wide
- Broadcast message to a specific Activity, Service, or Broadcast Receiver
- Request an action be performed on a particular piece of data
Application Components:
Broadcast Receivers Overview
Used to receive broadcast Intents.
Enables an application to listen for Intents that match some specified criteria.
- Broadcast Receivers start the application to react to any received Intent
- Perfect for creating event-driven applications
Application Components:
Content Providers Overview
The preferred means to share data across application boundaries.
- An Application’s Content Providers can be configured to allow access from other applications
- Can access CPs exposed by others
- Android devices include several native Content Providers that expose useful databases such as the media store and contacts.
Application Components:
Notifications Overview
Enable you to alert users to application events without stealing focus or interrupting their current Activity.
- Preferred technique for getting a user’s attention when app is not visible or active
- Typically triggered from within a Service or Broadcast Receiver
- Example:
- User alerted via Notification when a text message arrives
Overview of how Applications run
- Limited control over their own life cycle
- App components must listen for changes in application state and react accordingly
- Each app runs in its own process, running a separate instance of the Android Run Time
- Memory and process management is handled exclusively by the run time
- Android constantly and aggressively manages its resources to ensure a smooth and stable user experience
- Apps may be asked to release some resources
- Low priority apps may be terminated
Application Priority:
Basic Priority Rules
- The order in which processes are killed to reclaim resources is determined by priority of their hosted applications
- An application’s priority is equal to that of its highest-priority component
- If two apps have the same priority,
- the process which has been at that priority the longest will typically be killed first
- Interprocess dependencies:
- If an app has a dependency on a Service or Content Provider from a second app, the secondary app is assigned AT LEAST as high a priority as the application it supports
- The state/visibility of an app mostly determine its priority level
- Android selects apps to kill using a last-seen-first-killed pattern
- Processes consuming more memory are more likely to be killed
Application Priority:
Priority Levels
- Critical Priority:
- Active Process
- High Priority:
- Visible Process
- Medium Priority:
- Started Background Service
- Low Priority:
- Background Process
Application Priority:
Priority Levels:
Critical Priority
Active(foreground) processes that have application components the user is interacting with.
- Generally very few of these processes
- Active processes include one or more of the following components:
- Activities in an active state
- Broadcast receivers executing “onReceive” event handlers
- Services executing “onStart”, “onCreate” or “onDestroy” event handlers
Application Priority:
Priority Levels:
High Priority
Visible Processes
- Visible but inactive processes
- host “visible” Activities or foreground services
- Visible, but not in the foreground or responding to user input
- Happens when:
- Activity is only partially obscured( by a non-full screen or transparent Activity)
- Non-active window in a multi-window environment
Application Priority:
Priority Levels:
Medium Priority
Processes hosting background Services that have been started.
These services don’t interact directly with the user, so they receive a lower priority than visible Activities or foreground Services.
Application Priority:
Priority Levels:
Low Priority
Background Processes
Processes hosting Activities that aren’t visible and that don’t have any running services.
- When a user switches applications, the previous application goes to the background
- Generally a large number of background apps
Application Class:
Overview
- The Application object remains instantiated whenever the application is running
- Unlike Activities, it is not restarted as a result of configuration changes
- Extending the Application class enables you to respond to application-level events broadcast by the Android Run Time
- such as low memory conditions
- Instantiated when the application process is created.
- It is by nature a Singleton
Activities:
Activity Basics
- Each Activity represents a screen that can be presented to users
- The more complex the app, the more screens will likely be needed
- Typically includes at least:
- a “main Activity”
- primary interface screen
- handles the main UI functionality of the application
- Secondary Activities
- a “main Activity”
- To move between screens, a new Activity is started or the current Activity is returned from
Creating Activities:
General Steps
-
Extend the Activity class (or one of it’s subclasses)
- Probable subclass: AppCompatActivity
-
Register the Activity in the manifest
- This is necessary to use the Activity within an application
-
Assign a UI
- Use Fragments, layouts and Views
- Perform in “onCreate” event handler
- Use the setContentView method to assign View to the Activity
- Generally, assign a layout that is defined in your res/layouts folder:
- setContentView( R.layout.myLayout )
- Alternatively, create views programmatically
- Implement Functionality
Creating Activities:
Registering an Activity in the Manifest
- To use an Activity in an app, it must be registered in the AndroidManifest.xml file
- Add a new <activity></activity> tag within the <application></application> node of the manifest
- The <activity></activity> tag includes attributes for metadata, including:
- label, icon, required permissions, themes used
- Also includes a “name” attribute
- Can also add <intent-filter></intent-filter> nodes
- Specify the Intents that can be used to start an activity
- For an activity to be available from the application launcher, it must include an Intent Filter listening for the MAIN action and the LAUNCHER category
AppCompatActivity:
Overview
- An Activity subclass available from the Android Support Library
- Provides ongoing backward compatibility for features added to the Activity class in each new platform release
- It is considered best practice to use AppCompatActivity instead of the Activity class
Activity Life Cycle:
Important Terms and Ideas
- Activity Stack
- Also called “Back Stack”
- Android Memory Manager
- Least-Recently Used (LRU) list
- Activity States
- Major Activity events + handlers
- State transitions
- Full Lifetime
- Visible Lifetime
- Active Lifetime
*
Activity Life Cycle:
Activity Stack
Overview
- Also called the “back stack”
- A last-in, first-out collection of all the currently running activities
- The position of an Activity within the Activity stack determines its State
- New foreground Activities are added to the top of the stack
- The next Activity moves up and becomes active when:
- User presses the “back” button
- The current foreground Activity closes
Activity Life Cycle:
Least Recently Used (LRU) list:
Summary
Used to track the time since an Application was used.
When none of an Application’s Activities are visible, the App itself moves onto the LRU list.
The LRU list determines the order in which applications will be terminated to free resources.
Activity Life Cycle:
Activity States:
list the states
- Active
- Paused
- Stopped
- Inactive
Activity Life Cycle:
Activity States:
Active
- Activity is visible, focused, in the foreground and receiving user input
- It is at the top of the Activity stack
- Android attempts to keep it alive at all costs
- kills applications that own Activities further down the stack as need to ensure this Activity has the resources it needs
- Transitions:
- Paused when another Activity becomes active
- Stopped when no longer visible
Activity Life Cycle:
Activity States:
Paused
- Activity is visible but does not have focus
- May also be paused when the application is being used in a multi-window environment
- Only the Activity that the user last interacted with is considered Active
- Activity is treated as if it were active, but doesn’t receive user input events
- Only killed for resources in extreme cases
- Transitions:
- Stopped when the Activity is totally obscured
- All Activities transition through the Paused state before becoming Stopped
Activity Life Cycle:
Activity States:
Stopped
- When an Activity isn’t visible, it “stops”
- Remains in memory, retaining all state information
- Now a likely candidate for termination when system needs more memory
- Once in a Stopped State, it is important to:
- save data
- save current UI state
- stop any non-critical operations
- Transitions:
- becomes Inactive once Activity has exited or closed
Activity Life Cycle:
Activity States:
Inactive
- Activity doesn’t really “exist”
- In this state after being killed, and before it is launched
- Inactive Activities have been removed from the Activity Stack
- Transitions:
- To be displayed or used, the Activity must be restarted(this puts it into the Active state)
Activity Life Cycle:
Activity States:
Notes about Transitions
- Transitions between states should be invisible to the user
- No difference between an activity moving from paused, stopped or inactive state back to active
- It is important to save all UI state and persist all data when stopped
- Best Practice:
- Any time consuming state persistence operations should be performed when an Activity transitions to the stopped state( onStop() handler)
- Activities may transition between Paused and Active very frequently - So this transition should execute very quickly
Activity Life Cycle:
Activity States:
How does an App control its State Transitions?
It doesn’t.
State Transitions occur through User and System actions.
Similarly, the Android Memory Manager handles application termination.
Activity Life Cycle:
The Full Lifetime:
When it occurs
Between the first call to onCreate() and when the Activity is destroyed
onDestroy() is not necessarily called when the Activity is destroyed
Activity Life Cycle:
The Visible Lifetime:
When it occurs
The Visible Lifetime is the time between
starting an Activity - onStart()
and
stopping an Activity - onStop()
An Activity can have many Visible Lifetimes within one Full Lifetime
Activity Life Cycle:
The Active Lifetime:
When it occurs
The Active Lifetime
starts when Activity is resumed - onResume()
and
ends when Activity is paused - onPause()
An Activity is likely to go through MANY active lifetimes before it is destroyed
Activity Life Cycle:
Full Lifetime:
Important Event Handlers
-
onCreate()
- Initializes Activity and all components
- Objects should be created here
- If recreating a terminated Activity, receives a Bundle object containing state saved with onSaveInstanceState()
-
onDestroy()
- Clean up any resources created in onCreate(), ensure all external connections are closed
- Not guaranteed to be called when Activity destroyed
Activity Life Cycle:
Visible Lifetime:
Important Event Handlers
-
onRestart()
- Called before onStart(except for the first call)
- Implement special processing only needed when Activity restarts within its full lifetime
-
onStart()
- Register Broadcast Receivers for UI
- First Call: Start required UI updating processes
- else, resume processes stopped in the onStop() handler
-
onRestoreInstanceState(Bundle savedInstanceState)
- called when Activity is started after having been destroyed
- Restores previous UI state using the passed in savedState Bundle
-
onStop()
- unregister Broadcast Recievers for UI
- pause or stop:
- animations
- threads
- Sensor listeners
- GPS lookups
- Timers
- Services
- other processes used only for updating UI
Activity Life Cycle:
Active Lifetime:
Important Event Handlers
-
onResume()
- Resume any paused UI updates, threads or processes required by the Activity while it is active
-
onPause()
- Suspend UI updates, threads or processes not needed when Activity is not Active
-
onSaveInstanceState(Bundle savedInstanceState)
- Called when appropriate to save UI state changes at the end of the active lifecycle
- UI state is saved to savedInstanceState bundle
- savedInstanceState can be used in the onCreate() and onRestoreInstanceState() handlers in the future to restore the current UI state
Activity Life Cycle:
Important
Activity State
Event Handlers
- onCreate(Bundle savedInstanceState)
- onRestart()
- onStart()
- onRestoreInstanceState(Bundle savedInstanceState)
- onResume()
- onPause()
- onSaveInstanceState(Bundle savedInstanceState)
- onStop()
- onDestroy()
Memory Pressure:
Event used by the system to
request reduced memory usage
TrimMemory
individual components handle this by overriding the onTrimMemory() handler
Memory Pressure:
Overview
- The Android system will terminate apps without warning to free resources for active and visible apps
- It is ideal to retain as many background apps as possible, to improve experience of switching between apps
- The order of termination is determined by:
- Position on LRU list
- Amount of memory that would be freed
- App components are given a chance to free additional memory, making termination less likely, by implementing the onTrimMemory() handler
Memory Pressure:
onTrimMemory()
Level Parameters
- TRIM_MEMORY_RUNNING_MODERATE
- TRIM_MEMORY_RUNNING_LOW
- TRIM_MEMORY_RUNNING_CRITICAL
- TRIM_MEMORY_UI_HIDDEN
- TRIM_MEMORY_BACKGROUND
- TRIM_MEMORY_MODERATE
- TRIM_MEMORY_COMPLETE
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_RUNNING_MODERATE
App is running and not being considered for termination,
but the system is beginning to feel memory pressure
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_RUNNING_LOW
- App is running and not being considered for termination,
- System is running extremely low on memory
- System will now begin killing background processes if apps don’t free resources
- By releasing non-critical resources now, this app can prevent performance degradation and reduce the chance of other apps being terminated
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_UI_HIDDEN
- Application is no longer displaying a visible UI
- Good opportunity to release large resources that are only used by the UI
- It is considered good practice to release these resources here, rather than within the onStop handler
- Avoids purging/reloading UI resources if the UI quickly switches from hidden to visible
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_BACKGROUND
- Application is no longer visible and has been added to the least-recently used (LRU) list
- App is now a low-risk candidate for termination
- System is running low on memory and may already be killing other apps on the LRU list
- Release resources that are easy to recover now, to reduce system pressure and make application less likely to be terminated
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_MODERATE
- Application is in the middle of the LRU list
- The system is running low on memory
- If the system becomes further constrained for memory, there is a good chance your process will be killed
Memory Pressure:
onTrimMemory levels meaning:
TRIM_MEMORY_COMPLETE
- This app is one of, if not THE, most likely candidates for termination if the system does not recover memory immediately.
- Release absolutely everything that isn’t critical to resuming the application state
Fragments:
Overview
Fragments enable you to divide Activities into fully encapsulated, resusable components that each have their own lifecycle and state.
- Each Fragment is an independent module
- Loosely coupled, but tightly bound to the Activity
- A Fragment can be used in multiple activitities
- Can be added to, removed from, and exchanged within a running Activity
Fragments:
Creating a Fragment
- If the Fragment contains a UI, create an XML file to define the layout
- Create a new class that extends the Fragment class
- Note: The Fragment DOES NOT have to be registered in your manifest
- For Fragments that require a UI:
- Override the onCreateView method
- Inflate the layout
- or define programmatically
- onCreateView includes a parameter for the ViewGroup that will contain the Fragment, called “container”
- Override the onCreateView method
Fragment Lifecycle:
Basics
- Lifecycle events of Fragment mostly mirror those of its parent Activity
- When the Activity is active, a Fragment can still be added or removed, independently affecting its life cycle
- Most Fragment lifecycle events correspond to equivalents in the Activity class
Fragment Lifecycle:
Events that are specific to Fragments
-
Attaching
- Fragment is bound to it’s parent’s Context
- onAttach handler
-
Detaching
- Remove a Fragment from its parents
- or containing component destroyed
- onDetach handler
-
Create View
- Initializes/inflates the UI of the Fragment, gets references and binds data to the Views in the Fragment
- onCreateView handler
-
Destroy View
- Destroy the UI of the Fragment
- onDestroyView handler
Fragment Lifecycle:
Major Event Handlers
(12)
- onAttach()
- onCreate()
- onCreateView()
- onActivityCreated()
- onStart()
- onResume()
- onPause()
- onSaveInstanceState()
- onStop()
- onDestroyView()
- onDestroy()
- onDetach()
Fragment Lifecycle:
Major Event Handlers:
onAttach()
onAttach( Context context )
- Called when the Fragment is attached to its parent Activity
- Use to get a reference to a Context representing the parent component
Fragment Lifecycle:
Major Event Handlers:
onCreate()
onCreate( Bundle savedInstanceState )
- Called to do the initial creation of the Fragment
- Good practice to create any class-scoped objects here to ensure they are only created once during the Fragment’s lifetime
- Unlike Activity, Fragment UI is NOT inflated here, that is saved for onCreateView
Fragment Lifecycle:
Major Event Handlers:
onCreateView
onCreateView( LayoutInflater inflator,
ViewGroup container,
Bundle savedInstanceState)
- Called once the Fragment has been created in order for it to create is user interface
- Create, or inflate the Fragment UI, returning the View
- If Fragment has no UI, returns null
Fragment Lifecycle:
Major Event Handlers:
onActivityCreated()
onActivityCreated( Bundle savedInstanceState)
- Called once the parent Activity and the Fragment’s UI have been created
- Complete the Fragment initialization, particularly:
- anything that requires the parent Activity to be initialized
- or requires the Fragment’s View to be fully inflated
Fragment Lifecycle:
Major Event Handlers:
onStart()
onStart()
- Called at the start of the visible lifetime
- Apply any required UI change now that the Fragment is visible
Fragment Lifecycle:
Major Event Handlers:
onResume()
onResume()
- Called at the start of the active lifetime
- Resume any paused UI updates, threads, or processes required by the Fragment but suspended when it became inactive
Fragment Lifecycle:
Major Event Handlers:
onPause()
onPause()
- Called at the end of the active lifetime
- Suspend UI updates, threads or CPU intensive processes that don’t need to be updated when Activity is not the active foreground activity
- Persist all edits or state changes
- After this call, process is likely to be killed
Fragment Lifecycle:
Major Event Handlers:
onSaveInstanceState()
onSaveInstanceState(
Bundle savedInstanceState)
- Called to save UI state changes at the end of the active lifecycle
- Save UI state changes to the savedInstanceState
- This bundle will be passed to onCreate(), onCreateView(), and onActivityCreated() if the parent Activity is killed and restarted
Fragment Lifecycle:
Major Event Handlers:
onStop()
onStop()
- Called at the end of the visible lifetime
- Suspend remaining UI updates, threads, or processing that are not required when the Fragment isn’t visible
Fragment Lifecycle:
Major Event Handlers:
onDestroyView
onDestroyView()
- Called when the Fragment’s View has been detached
- Clean up resources related to the View
Fragment Lifecycle:
Major Event Handlers:
onDestroy()
onDestroy()
- Called at the end of the full lifetime
- Clean up any resources, including ending threads, closing database connections, etc
Fragment Lifecycle:
Major Event Handlers:
onDetach()
onDetach()
- Called when the Fragment has been detached from the parent Activity
- Clean up any references to the parent Activity
- including references to its Views or classes, typically setting those references to null
Fragment Manager:
Basics
- Each Activity includes a Fragment Manager
- Accessed using the method:
- getSupportFragmentManager()
- Accessed using the method:
- It provides the methods used to access the Fragments that are currently added to the Activity
- Also provides methods to perform Fragment Transactions to add, remove and replace Fragments
How to Add Fragments to Activities
Two Basic Ways:
- Include the Fragment within the parent Activity’s layout, using the <fragment> tag
</fragment><ul>
<li>When layout is inflated, the fragment becomes a View Group within the view hierarchy</li>
<li>Works well for static layouts based on various screen sizes</li>
</ul></fragment>
or
- Create layouts that use container Views, then place Fragments into them at run time
- This allows you to dynamically modify the layout by adding,removing and replacing fragments based on the application state
Fragment Transactions:
Basics
- Used to add, remove and replace Fragments within an Activity at run time
- Allows for dynamic layouts
- Can include any combination of supported actions:
- adding, removing, or replacing Fragments
- Support transition animations
- Obtained from Fragment Manager, has actions added to it, then committed to perform the Transaction
Fragment Transactions:
Replacing a Fragment
- Get new Fragment Transaction:
- FragmentTransaction trans = fragmentManager.beginTransaction();
- Use the replace() method of the transaction, specifying the container ID, a new Fragment to replace the old one, and optionally a Tag for the new Fragment:
- trans.replace( R.id.details_container,
new DetailFragment(some_index),
FRAG_TAG);
- Commit the Transaction:
- trans.commitNow();
Fragment Transactions:
Removing a Fragment
- Get new Fragment Transaction:
- FragmentTransaction trans = fragmentManager.beginTransaction();
- Get reference to the Fragment, through the Fragment Manager, using either method:
- findFragmentById() or
- findFragmentByTag()
- Pass the found Fragment instance as a parameter to the remove() method of a Fragment Transaction:
- trans.remove(fragment)
- Commit the Transaction:
- trans.commitNow();
Fragment Transactions:
Adding a Fragment
- Create the Fragment Tag(optional):
- String FRAG_TAG = “myTag”
- Have handle to FragmentManager ready
- Get new Fragment Transaction:
- FragmentTransaction trans = fragmentManager.beginTransaction();
- Specify the “add” action with the container, fragment and tag:
- trans.add(R.id.details_container, new DetailFragment(), FRAG_TAG);
- Commit the Transaction:
- trans.commitNow();
Fragments:
Finding Fragments
with the
Fragment Manager
Two basic methods:
-
findFragmentById( int frag_id | container_id)
- If Fragment was added in the layout, use the fragment’s own id ( R.id.MyFragment)
- If Fragment dynamically added at runtim, use the id of the Container (R.id.my_container)
-
findFragmentByTag(**String tag**)
- essential for dealing with non-UI Fragments, as they are not part of the View Hierarchy
-
findFragmentByTag(**String tag**)
Fragments:
Populating Dynamic Layouts and
Dealing with Configuration Changes:
Tips and Best Practices
- Define only the parent containers with the XML layout
- Populate the parent containers exlusively using Fragment Transactions
- This ensures consistency when configuration changes(such as screen rotations) cause the UI to be re-created
- Android persists the Fragment layout and associated back stack when an Activity is restarted due to configuration changes
- Fragment Manager will attempt to restore the Fragments in each container after configuration changes
- Any view containers that are involved in any transactions should be included in all layout variations
- If not, Fragment manager may attempt to restore Fragments in containers that no longer exist
- A Fragment container can be removed from a given orientation layout by marking its “visibility” attribute as “gone” in the layout definition
Fragment Transactions:
Using the Back Stack
- Fragment Transactions can be added to the Back Stack
- simply call the Fragment Transaction method
- addToBackStack( BACKSTACK_TAG )
- Prior to committing the Transaction
- simply call the Fragment Transaction method
- Note: Must use the commit() method afterwards, cannot use commitNow()
- Pressing the back button will reverse the Transaction
- If any removals or replacements occured, the previous fragments are restored from the backstack
Fragment Transactions:
Animating Fragment Transactions
- Simply use the setTransition( Transition_ID ) method on a transaction prior to committing
- There are several default animations, defined by the set of constants in FragmentTransaction class:
- TRANSIT_FRAGMENT_*
- Can also set custom animations
- Prior to add or remove methods, use the method:
- setCustomAnimations( anim_in, anim_out )
- Accepts two Object Animator XML resources, one for fragments being added to the layout, one for fragments being removed
Fragments:
Communicating between
Fragments and Activities
- A Fragment may need to share events with its parent Activity
- Ex: Signaling UI selections
- Good practice is to create a callback interface within the Fragment
- The host Activity must then implement this interface
- In the onAttach() method, the Fragment adds the Context(Parent Activity) as a listener
- Fragment can then call methods defined in the interface when it wants to
- Can also just use the getContext method to get a pointer to the host activity
- It is considered best practice for Fragments not to communicate directly with each other, but to go through the parent activity
Fragments:
Fragments Without User Interfaces
- Useful for providing background behavior which persists across Activity restarts caused by configuration changes
- Added to the Activity ar runtime using a Fragment Transaction with the add method.
- Later found using a Tag
- Select a Fragment to retain its current instance using the setRetainInstance() method
- The Fragment instance will be retained when the parent Activity is destroyed and re-created
- When parent destroyed, receives the onDetach event
- When new parent Activity is instantiated, receives onAttach, onCreateView and onActivityCreated events