Android Fragment

This article will give an insight into the Android Fragment.For the organization purpose of our application code we use fragment components .These components has their own life cycle and their own user interface. It can be defined through layout files or coding. Fragments always run in the context of an Activity. The Activity is stopped or destroyed the corresponding fragments are also stopped or destroyed. The base class of fragment is android.app.Fragment and also we are using some more special classes like ListFragment or DialogFragment.

The android:name attributes points to the Fragments class when the fragment component is defined in an XML layout file. For the creation of fragments in its user interface we called onCreateView() and onStart() helps to display the Fragments. Fragments helps dynamically added and removed mechanism from an Activity through Fragment transactions.

Activity Life cycle

For controlling the activity life cycle we are implementing callback methods. An activity stays on three different states.

1)      Resumed

This is a running state.  The activity is in the foreground of the screen and has user focus.

2)      Paused

The paused activity is completely alive but it destroyed by the system in extremely low memory situations.

3)      Stopped

The stopped activity is a background activity. A stopped activity is alive and this activity is no longer visible to the user and it can be killed by the system when memory is needed elsewhere.

Eg: –

Implementing the lifecycle callbacks

>public class ExampleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
}

For implementing all the method together in a lifecycle we checks three different nested loops in the activity lifecycle.

1)      Entire lifetime

This activity is call between onCreate() and onDestroy() method. OnCreate() is used for defining the layout and onDestroy() helps to release all the remaining resources.

2)      Visible lifetime

This activity is call between onStart() and onStop() method. onStop() is called when a new activity starts and this one is no longer visible.

3)      Foreground lifetime

This activity is call between onResume() and onPause() method. OnPause() is called when the device goes to sleep or when a dialog appears.

The below figure shows these loops and the paths an activity might take between states. The rectangle represents the callback methods.

Android Activity LifeCycle
Android Activity LifeCycle

The following methods explain the working of activity lifecycle’s callback methods.

  • onCreate():- This method is called when the activity is first created. This is where you should do all of your normal static set up — create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity’s previous state, if that state was captured. It always followed by onStart().
  • onRestart() :-This method is called after the activity has been stopped, just prior to it being started again and it also followed by onStart()
  • onStart() :- It called just before the activity becomes visible to the user and it followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.
  • onResume():- It called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it and followed by onPause().
  • onPause():- It is called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns. It always followed either by onResume() if the activity returns back to the front, or by onStop() if it becomes invisible to the user.
  • onStop():-It called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it and followed either by onRestart() if the activity is coming back to interact with the user, or by onDestroy() if this activity is going away.
  • onDestroy():-This method is called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.

Usage of Fragments

Fragments are easy to re-use components in different layout.

Eg: – We can build single-pane layouts for handsets (phones) and multi-pane layouts for tablets. On a tablet the details immediately on the same screen on the right hand side if you click on item. In a handset we jump to a new detail screen. In this mechanism it creates the two fragments.

  1. Main
  2. Detail

This consists of main activity and detailed activity. In a tablet the main activity includes both fragments in its layout on a handset includes only the main fragment. FrameManager helps to identify a fragment.

Eg: –

 DetailFragment fragment = (DetailFragment) getFragmentManager().
findFragmentById(R.id.detail_frag);
if (fragment==null || ! fragment.isInLayout()) {
// start new Activity
}
else {
fragment.update(...);
}

For creating the different layout with fragments we can

1)      Use one activity, which shows two Fragments for tablets and only one on handsets devices. Here we switch the Fragments in the activity whenever necessary. This requires that the fragment is not declared in the layout file as such Fragments cannot be removed during runtime and also requires an update of the action bar if the action bar status depends on the fragment.

2)      Use separate activities to host each fragment on a handset.

Eg:- when the tablet UI uses two Fragments in an activity, use the same activity for handsets, but supply an alternative layout that includes just one fragment.

When you need to switch Fragments, start another activity that hosts the other fragment.

Create a new project

We can create a new project called com.android.fragments with an Activity called MainActivity.

Create layouts for portrait mode

We can create or change the layout files in the res/layout/ folder. For this mechanism we first create the file called details.xml by using the below code and this layout is used by the DetailFragment.

Eg: –

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/detailsText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_marginTop="20dip"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="30dip" />
</LinearLayout>

Change the existing “main.xml” file. This layout will be used by MainActivity in landscape mode and shows two Fragments.

Eg: –

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:id="@+id/listFragment"
android:layout_width="150dip"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
></fragment>
<fragment
android:id="@+id/detailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- Preview: layout=@layout/details -->
</fragment>
</LinearLayout>

Create Fragment classes

For creating the ListFragment we are using the following code.

Eg: –

package com.android.fragments;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ListFragment extends android.app.ListFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, values);
setListAdapter(adapter); }
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String item = (String) getListAdapter().getItem(position);
DetailFragment fragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.detailFragment);
if (fragment != null && fragment.isInLayout()) {
fragment.setText(item);
} else {
Intent intent = new Intent(getActivity().getApplicationContext(),
DetailActivity.class);
intent.putExtra("value", item);
startActivity(intent);
}    }  }

Create the DetailFragment class.

Eg: –

package com.android.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class DetailFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("Test", "hello");
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.details, container, false);
return view;
}
public void setText(String item) {
TextView view = (TextView) getView().findViewById(R.id.detailsText);
view.setText(item);
}
}

Activities

We can create a new Activity called DetailActivity with the following class.

Eg: –

package com.android.fragments;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.widget.TextView;
public class DetailActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Need to check if Activity has been switched to landscape mode
// If yes, finished and go back to the start Activity
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
setContentView(R.layout.details_activity_layout);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String s = extras.getString("value");
TextView view = (TextView) findViewById(R.id.detailsText);
view.setText(s);
}
}
}

MainActivity will remain unmodified.

Eg: –

package com.android.fragments;
import android.app.Activity;
import android.os.Bundle;
We run our application in portrait mode we should see only one fragment. Use Ctrl+F11 to switch the orientation.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}