mobappdev (fall 2013): fragments, fragment use guildelines, fragment's lifecycle: construction...
TRANSCRIPT
MobAppDev
Fragments, Fragment Use Guidelines, Fragment's Lifecycle: Construction &
Destruction Callback Chains
Vladimir Kulyukin
www.vkedco.blogspot.com
Outline
● Review– Custom Views & Custom Adapters– Compiled and Non-compiled Resources
● Fragments & Fragment Use Guidelines● Fragment Lifecycle: Construction & Destruction
Callback Chain
Review
Review: Custom Views
ListView 01 ListView 02 ListView 03
Populating ListView 02// this is a method in the main activity ListOfMathematiciansAct.java
private void populateListViewTwo() {
mListOfMathematicians = mRes.getStringArray(R.array.list_of_famous_mathematicians);
ArrayList<Mathematician> mathematicians =
new ArrayList<Mathematician>();
for(String name : mListOfMathematicians) {
String[] fnln = name.trim().split(" ");
mathematicians.add(new Mathematician(fnln[0],fnln[1]));
}
getListView().setAdapter(new ArrayAdapter<Mathematician>(this,
R.layout.mathematician_view_1,
mathematicians));
}
source code is here
Custom Views & Custom Adapters
● No custom views & no custom adapters are needed when using standard TextViews and ListViews
● Custom views are needed when some fancy text manipulation and background graphics are required (not custom array adapters are needed if the standard adapters can be generalized to custom objects)
● Custom views and adapters are required when both the views and the adapters must be customized to populate the ListView
Populating ListView 03// this is a method in the main activity ListOfMathematiciansAct.java
private void populateListViewThree() {
mListOfMathematicians = mRes.getStringArray(R.array.list_of_famous_mathematicians);
ArrayList<Mathematician> mathematicians =
new ArrayList<Mathematician>();
for(String name : mListOfMathematicians) {
String[] fnln = name.trim().split(" ");
mathematicians.add(new Mathematician(fnln[0], fnln[1]));
}
MathematicianViewArrayAdapter adptr =
new MathematicianViewArrayAdapter(this,
R.layout.mathematician_view_2,
mathematicians);
getListView().setAdapter(adptr);
}
source code is here
Resource Compilation
● The resource compiler is part of the Android Packaging Tool (AAPT)
● The resource compiler compiles all resources except those in /res/raw/ and places them into the .apk file
● The .apk file is similar to the Java .jar file and contains all the application's code and resources
● The .apk file is installed on the device
Colors /res/values/some_file.xml Color codes; exposed in R.java as R.color.*
Dimensions /res/values/some_file.xml Sizes of various elements in pixels, inches, millimeters; exposed in R.java as R.dimen.*
Images /res/drawable/some-subfolder/some_file.xml
Image resources (.jpg, .gif, .png); Exposed through R.java as R.drawable.*
Resource Compilation
Raw Assets
● Project directory /assets/ contains raw files● Unlike /res/ directory, /assets/ may contain
arbitrarily many sub-directories● Unlike files in /res/ directory, /assets/ directory
do not generate resource IDs● Relative path names must be used to access files
in /assets/
What Fragments Are &
Fragment Use Guidelines
Fragments
● It is difficult to do multiple things on the same screen with Activities
● A typical example is displaying a list of e-mails on the left of the screen and reading a specific e-mail on the right
● Fragments also allow developers to focus more on the application logic and let Android worry about layout management on different screen sizes
Fragments as Sub-Activities
● Fragments can be loosely construed as sub-activities● Fragments are contained within a specific activity● Fragments are tied to an activity because they can exist
in the context of a specific activity● It is possible to create an activity's layout and use a
fragment for one component in that layout
Use Guidelines
● If you plan to develop GUIs for a specific Android platform, fragments should probably not be considered
● If you plan to develop GUIs where the logic can be developed as a stack on activity screens, fragments should (probably) not be considered
● If GUIs are of secondary importance to your application, because the primary focus is the backend computation (e.g., cloud computing, remote databases), fragments should not be considered
● If you plan to develop GUIs for a specific Android platform, fragments should probably not be considered
● If you plan to develop GUIs where the logic can be developed as a stack on activity screens, fragments should (probably) not be considered
● If GUIs are of secondary importance to your application, because the primary focus is the backend computation (e.g., cloud computing, remote databases), fragments should not be considered
Use Guidelines
● Fragments become a top priority if you want to reuse a UI component across multiple devices and screen resolutions
● For example, suppose you are developing a UI that consists of a list of items displayed on the left and an item's content displayed on the right
● When the target device is in landscape mode, two components display nicely
● When the target device is in portrait, simultaneous display may become a problem
Use Guidelines
● If you are managing activities, you need to save the current state of an activity and restore it in onCreate() when Android re-creates the activity
● Fragments make activity persistence more manageable, because they can take care of their own recreation (to some extent)
● Each fragment has its own layout that can be used in multiple configurations
Quiz Question
What happens when you press the Back button within an Activity?
Quiz Answer
● When the user presses the Back button, the user is taken out of the activity (i.e., the activity is not necessary destroyed but is popped off the activity stack)
● If an activity uses fragments and the user presses the Back button within a fragment, the user is not taken out of the activity
● Each activity has a stack of fragments and the user is simply taken to the next fragment on the stack or to the main activity layout
Fragment vs Activity in the OOP Hierarchy
● Activity is a subclass of Context● Fragment is a subclass of java.lang.Object● Fragment does not extend Activity● The Fragment class can be extended and its
methods can be overriden
Fragment's Implementation Details
● Fragments have their own Bundles that they can use for their own initialization
● Fragments, like Activities, can be saved and re-stored by the system
● When the system re-creates a Fragment (i.e, creates a new Fragment from an old Bundle) it will pass to it the Bundle object that was saved when the old Fragment was destroyed
Fragment's Implementation Details
● Since the system passes to a newly created Fragment the Bundle object that was saved when the old Fragment was destroyed, each Fragment must have a default constructor
● When a fragment is swapped with another fragment, the fragment-switching transaction can be saved on a back stack
● The back stack is a stack data structure is managed by the FragmentManager
● Each Activity has its own FragmentManager
● Each FragmentManager knows its Activity
Fragment's Implementation Details
● Since a fragment is tied to an Activity, it has access to the Activity's resources
● A fragment has a unique tag and an ID
● Tags and IDs can be used to find specific fragments
● Fragments can save its current state to a Bundle object
● The saved Bundle object will be passed by the system to the following callbacks: onCreate(), onInflate(), onCreateView(), and onActivityCreated()
Fragment Lifecycle
Lifecycle: Fragment vs Activity
● As with Activities, it is important to understand Fragments' lifecycles to know when and what you can do with Fragment objects
● Fragment's lifecycle is more involved than Activity's lifecycle
● The differences are primarily due to the fact that Fragments are tied to specific Activities
● A Fragment can go through multiple states as its host Activity goes through one or none
Fragment Construction Callback Chain
Fragment Factory Instantiation
public static XFragment newInstance(int value) {
XFragment xf = new XFragment();
Bundle b = new Bundle();
b.putInt(“some key value”, value);
xf.setArguments(b); // this is how you pass arguments to
// newly created fragments
return xf;
}
Lifecycle: onInflate() Callback● The next thing after newInstance() that may be called is
onInflate()
● This callback is called if and only if the fragment is specified with the <fragment></fragment> tag in some XML layout
● This callback has access to the fragment's activity, the AttributeSet defined in the <fragment></fragment> tag and a saved Bundle (if there is one)
● The saved Bundle is saved with onSaveInstanceState()
● After onInflate() returns the fragment is not yet associated with the activity: it is not possible to do anything with the GUI
Lifecycle: onAttach() Callback
● After the fragment is associated with the Activity, its reference is passed to onAttach() and onAttach() is called
● The activity reference can be used to determine the information about the enclosing activity, get access to its resources, etc
● The associated activity can also be used as a Context for all operations that require a Context
● Fragment.getActivity() is the method that always returns a reference to the attached activity
Fragment.getArguments() & .setArguments()
● The fragment's initialization arguments are available through the lifecycle of the fragment with the call to Fragment.getArguments()
● Fragment.setArguments() cannot be called after the fragment is attached to the activity
● Fragment.setArguments() should be called in newInstance() before the fragment is attached to the activity
Lifecycle: onCreate() Callback
● The callback onCreate() is the next in the callback chain
● This callback gets the saved Bundle if there is one
● This callback is a nice place to create background threads
● The background threads may, for example, get some data that the fragment will use in its UI
● All blocking calls (e.g., I/O) should run on the background thread
● A Handler can be used to update the UI thread when the data is ready
Lifecycle: onCreateView() Callback
● The callback onCreateView() is called after onCreate()
● This callback gets as its arguments the LayoutInflater and the saved Bundle
● The association of the fragment's view hierarchy to the parent's view hierarchy happens automatically (the developer should not even try do it manually)
● Some fragments do not have a view hierarchy, to begin with: they exist to support some background computation
Example
public View onCreateView(LayoutInflater inf, ViewGroup container,
Bundle savedInstanceState) {
If ( container == null ) return null; // no view hierarchy
View v = inf.inflate(R.layout.my_layout, container, false);
TextView tv = (TextView) v.findViewById(R.id.my_text_id);
tv.setText(some_data_bundle[ this.getPosition() ];
return v;
}
Lifecycle: onActivityCreated() Callback
● This callback after the associated activity completes its onCreate() callback
● In this callback, it can be assumed that the activity's view hierarchy and the fragment's view hierarchy are available and can be accessed
● All final UI tweaks, if there are any, should occur in this callback: a typical example is restoring data in the UI from the saved Bundle
● It can also be assumed that all other fragments have been attached to the associated activity
Lifecycle: onStart() Callback
● The callback onStart() is called onActivityCreated()● The fragment is now visible to the user● This callback can be used to access and inflate all the
fragment's GUI components● The fragment is visible to the user but is not interacting
with the user yet
Lifecycle: onResume() Callback
● The callback onResume() is called after onStart()
● This callback is the last one before the user starts interacting with the fragment
● For example, if your fragment contains a camera preview/voice search, the user can now take a picture/speak to the voice search
● Now the user interacts with the application until the user 1) presses the Back button; 2) the Home Button; and 3) launches another application
Fragment Destruction Callback Chain
Lifecycle: onPause() Callback
● This is the first callback in the fragment destruction chain
● If your fragment has a TTS engine running, this is the place to pause it or shut it down
● This callback allows your application to be a responsible citizen: do not keep playing music or reading text out loud after another application takes over and becomes visible
Lifecycle: onSaveInstanceState() Callback
● This callback is used to persist data
● Like activities, fragments can persist states in Bundles
● Bundle savings should be minimal and necessary
● This method is typically called after onPause()
● The only guarantee Android gives the developer is that this method will be called before onDestroy(): so be careful what you save (do not save references, save String IDs instead)
Lifecycle: onStop() Callback
● The callback onStop() is similar to the activity's onStop()
● Do the necessary cleanup here● The fragment is not destroyed yet: it can go back
to onStart() and then onResume() if the user comes back to it
Lifecycle: onDestroyView(), onDestroy(), onDetach()
● This method is called after the view hierarchy (if any) that was created in onCreateView() has been detached from the fragment
● onDestroy() is called when the fragment is no longer in use
● When onDestroy() is called the fragment is still attached to the activity and can be found through a reference and/or a tag
● The callback onDetach() disassociates the fragment from the activity: the fragment is no longer findable and its resources should have been released
Lifecycle: setRetainInstance()
● This method, it is not a callback though, allows the developer to request Android not to destroy the fragment completely
● The logic here is simple: when the activity is destroyed the developer may want to specify that some of its fragments stay in memory so that if and when the activity restarts the old fragment is attached back to it instead of being created from scratch
● The place to do it is in onCreate(): just say setRetainInstance(true)
Lifecycle: onDetach() Callback
● As with Activities, it is important to understand Fragments' lifecycles to know when and what you can do with Fragment objects
● Fragment's lifecycle is more involved than Activity's lifecycle
● The differences are primarily due to the fact that Fragments are tied to specific Activities
● A Fragment can go through multiple states as its host Activity goes through one or none
References
● http://developer.android.com/guide/components/fragments.html
● S. Komatineni & D. MaClean. Pro Android 4. APRESS
● R. Meier. Pro Android 4 Application Development. WROX