Sunday, November 24, 2013

Android Fragment Summary I

Activities are not built to provide UI flexibility. An activity is tightly coupled with its view. The view that the activity inflates in the call to SetContentView(...) is tied to the activity until death do them part. We cannot swap out an activity's entire view (without destroying the activity) or pass a view from one activity to another at runtime.

Fragments were introduced in API level 11, so we have to find a way to ensure its compatibility with older versions of Android. The support library provides  fragment-related class (android.support.v4.app.Fragment). Also for lower API levels, we use FragmentActivity, which is an Activity subclass that provides the fragment-managing capabilities of the newer Activity class.

To host a UI fragment, an activity must

  • define a spot in its layout for the fragment's view.
  • manage the lifecycle of the fragment instance.

Since a fragment works on behalf of an activity, its state should reflect the activity's state. One critical difference between the fragment lifecycle and the activity lifecycle is that fragment lifecycle methods are called by the hosting activity, not the OS. Fragments are the activity's internal business, the OS knows nothing about the fragments.

There are two approaches to host a UI fragment in an activity:

  • add the fragment to activity's layout
  • add the fragment in the activity's code
The first approach is known as using a layout fragment. It is simple but inflexible. Adding the fragment to the activity's layout hard-wires the fragment and its view to the activity's view and cannot swap out that fragment during the activity's lifetime.
(continue after C13...)

The second approach is the more complex way to host, but it is the only way to have control at runtime over the fragments. You will be adding a UI fragment in the hosting activity's code, but you still need to make a spot (FrameLayout) for the fragment's view in the activity's view hierarchy. Notice that the container view is completely generic; it does not name any classes, so we can use the same layout to host other fragments.

Creating a UI Fragment
The steps to creating a UI fragment are the same as those we followed to create an activity:

  • compose an interface by defining widgets in a layout file
  • create the class and set its view to be the layout that you defined
  • wire up the widgets inflated from the layout in code
There are a couple of things to notice in implementing Fragment.onCreate(Bundle).
First, Fragment.onCreate(Bundle) is a public method whereas Activity.onCreate(Bundle) is protected. Fragment.onCreate(...) and other Fragment lifecycle methods must be public because they will be called by whatever activity is hosting the fragment. 
Second, similar to an activity, a fragment has a bundle to which it saves and retrieves its state. You can override Fragment.onSaveInstanceState(Bundle) for your own purpose just like with Activity.onSaveInstanceState(Bundle).
Third, what does not happen in Fragment.onCreate(..): you do not inflate the fragment's view. You configure the fragment instance in Fragment.onCreate(...), but you create and configure the fragment's view in another fragment lifecycle method:

  public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)

Adding a UI Fragment to the FragmentManager
When the Fragment class was introduced in Honeycomb, the Activity class was changed to include a piece called the FragmentManager.
The FragmentManager handles two things: a list of fragments and a back stack of fragment transactions.

Fragment transactions are used to add, remove, attach, detach, or replace fragments in the fragment list. They are the heart of how you use fragments to compose and recompose screens at runtime.




Android Programming Basic Concepts

1. An activity is an instance of ACTIVITY, it is responsible for managing user interaction with a screen of information.
2. A layout defines a set of user interface objects and their position on the screen, which is written in XML.
3. Widgets are the building blocks you use to compose a user interface. Every widgets is an instance of the View class or one of its subclasses. Every widgets has a corresponding XML element. Each element has a set of XML attributes. Each attribute is an instruction about how the widget should be configured.
4. FrameLayout, TableLayout, RelativeLayout and LinearLayout are subclasses of ViewGroup, which is a subclass of View.
5. A resource is a piece of your application that is not code, such as image files, audio files and XML files. Android generates a resource ID for the entire layout and for each string, but it does not generate IDs for the individual widgets, since not every widget needs a resource ID.
6. The manifest is an XML file containing metadata that describes your application to the Android OS.
The file is always named AndroidManifest.xml, and it lives in the root directory of your project. Every activity in an application must be declared in the manifest so that the OS can access it.
7.  An intent is an object that a component can use to communicate with the OS. Activities, services, broadcast receivers and content providers are all components. When you create an Intent with a context and a class object, you are creating an explicit intent. Explicit intents are used to start activities within your application. public Intent(Context packageContext, Class<?> cls). When an activity in your application wants to start an activity in another application, you create an implicit intent.


Saturday, November 23, 2013

Android Activity Lifecycle Summary

Every instance of Activity has a lifecycle. During this lifecycle, an activity transitions between three possible states: running, paused, and stopped. For each transition, there is an method that notifies the activity of the change in its state. We take advantage of these methods to do some work at transitions.
Note: you never call any of the Activity lifecycle methods yourself. We override them in activity subclasses, and Android calls them at the appropriate time.
   To see when android calls these methods, we can override methods with d(String tag, String msg) method which is in android.util.Log.

1. onCreate(Bundle): The OS calls this method after the activity instance is created but before it is put on screen.
  • inflating widgets and putting them on screen by SetContentView(int) method.
  • getting references to inflated widgets.
  • setting listeners on widgets to handle user interaction.
  • connecting to external model data.
  One of the case that we want to override onCreate(Bundle) is to get saved data after rotation. For example: 
  onCreate() {
   ...
   if (savedInstancesState != null) {
      variable = savedInstanceState.getInt(KEY, value);
   }
  }

Saving data is done by overriding OnSaveInstanceState(Bundle) method and we need to have a key-value pair which will be saved in the bundle. onSaveInstanceState method is normally called by the system before onPause(), onStop(), and onDestroy(). The data is saved to the Bundle object, the Bundle object is then stuffed into your activity's activity record by the OS.

Note that the types that you can save to and restore from a Bundle are primitive types and objects that implement the Serializable interface. When you creating custom classes, be sure to implement Serializable.

2. onPause()
3. onStop() 
   A stopped activity's survival is not guaranteed. When the system needs to reclaim memory, it will destroy stopped activities.
4. onDestroy()