Friday, April 7, 2017

Understanding Android fragment

Android fragment provides a way to reuse a UI component with the related UI layout and java event handling code.

The interface of a fragment to the outside world is the java class inherited from Fragment class. So when an activity includes a fragment in its UI layout, it includes a Fragment element indicated by the fragment's java class name in its layout xml file. At run time, when the activity's UI layout is inflated, it will initialize the fragment java class, which will load the fragment's own UI layout. As a result, Fragment only exposes to outside world as a java class, and its UI element detail is hidden from the outside. In this way, the logic and UI layout are enclosed inside the fragment's internal space.

The fragment's java class is also responsible to communicate to holding activity to handle the UI event, basically, it calls getActivity() to get the holding activity, and then calls the related method defined in the Activity class.

Similarly, dynamic fragment loading will add an instance of fragment java class by fragment manager transaction, which has a parameter to indicate where the fragment ui element will be added.

There is a unique usage of dynamic fragment to retain the state of the fragment after configuration change. By default, when device rotation changes, the activity and its holding fragment will be destroyed and re-created again. However, if setRetainInstance(true) is called on the fragment object in Fragment.onCreate method, then when device rotation changes, the fragment object will not be destroyed along with the activity, so it still hold its existing state. Note although the Fragment object is not created again, and onCreate is not called as well, the onCreateView is still be called so that Fragment can update its UI layout after the device orientation change. This feature only applies to fragment created dynamically.

@Overridepublic void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  setRetainInstance(true);
}