Activities vs. Fragments in Android

Android API version 3.0, known as Honeycomb, introduced a new concept called “fragments”.  What are fragments and why would you want to use one?  Read on.

In Android, a configuration change (which includes turning the phone sideways to view the screen in the landscape direction) causes the currently running activity to be stopped, reloaded, and re-rendered using the new configuration parameters.  (I’m sure iOS developers will be quick to point out this “feature” is missing in their stack.)  In doing so, your app will lose all the state information from the activity instance that was originally running.  Wouldn’t it be nice to keep that around?

Enter fragments.  Fragments are UI components (though it is possible to have non-UI fragments) that have the ability to retain state across configuration changes.  Fragments must always be associated with an activity, but with a quick call to setRetainInstance(true), the fragments that were associated with an activity will re-attach themselves to the new instance of an activity and retain their previous state.

To prove that fragments stay around, we’ll create two separate fragments, each of which chooses a random id when it is constructed.  Then we’ll attach both fragments to an activity.  The first fragment will be initially visible and the second fragment will be hidden.  When you click on a button on the first fragment, it will show you the second, and vice versa.  Then you can examine the ids to make sure the original fragments really are staying around.

This is a useful technique that can be used on smaller devices to show the UI a piece at a time.  On larger devices, you could define a layout that shows both fragments at once.  Fragments allow you to build your UI as a series of smaller, reusable graphical elements that you arrange as needed based on the device’s capabilities.

Let’s start by creating a FirstFragment class and the SecondFragment class.  I’ll assume that readers are familiar with handling onClick events, so won’t bother explaining that.  So that it is clear which fragment you are looking at, each fragment will have an id.

public class FirstFragment extends Fragment {

        public static final String TAG = "FirstFragmentTag";
        int key;

        public FirstFragment() {
                this.setRetainInstance(true);
                Random random = new Random();
                key = random.nextInt();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                Log.i(TAG, "onCreateView");
                View view = inflater.inflate(R.layout.first_fragment_layout, container, false);
                TextView textView = (TextView) view.findViewById(R.id.firstFragmentTextView);
                textView.setText(textView.getText() + "" + key);
                Button button = (Button) view.findViewById(R.id.goToSecondFragmentButton);
                button.setOnClickListener(new View.OnClickListener() {
                        public void onClick(View v) {
                                SecondFragment secondFragment = (SecondFragment) FirstFragment.this.getActivity()
                                                .getSupportFragmentManager().findFragmentById(R.id.secondFragment);
                                secondFragment.getView().setVisibility(View.VISIBLE);
                                FirstFragment.this.getView().setVisibility(View.GONE);
                        }
                });
                return view;
        }
}
public class SecondFragment extends Fragment {
        protected static final String TAG = "SecondFragmentTag";
        int key;

        public SecondFragment() {
                this.setRetainInstance(true);
                Random random = new Random();
                key = random.nextInt();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                Log.i(TAG, "onCreateView");
                View view = inflater.inflate(R.layout.second_fragment_layout, container, false);
                TextView textView = (TextView) view.findViewById(R.id.secondFragmentTextView);
                textView.setText(textView.getText() + "" + key);
                Button button = (Button) view.findViewById(R.id.goToFirstFragmentButton);
                button.setOnClickListener(new View.OnClickListener() {

                        public void onClick(View v) {
                                FirstFragment firstFragment = (FirstFragment) SecondFragment.this.getActivity()
                                                .getSupportFragmentManager().findFragmentById(R.id.firstFragment);
                                firstFragment.getView().setVisibility(View.VISIBLE);
                                SecondFragment.this.getView().setVisibility(View.GONE);
                        }

                });
                return view;
        }
}

 

 

The layout for each fragment will consist of a TextView (to show the id), an ImageView (to show a different graphic), and a Button (to navigate to the other fragment).  The main activity layout will consist of a LinearLayout that contains both the FirstFragment and the SecondFragment.  The FirstFragment will have its visibility set to “visible” and SecondFragment will have its visibility set to “gone”.  Check out the file here.

 

The FirstFragment layout and the SecondFragment layout define how each fragment will look.

 

To prove that these fragments retain their state, run the program and then turn your phone to put it into landscape mode.  Check to see if the ids stay the same for each fragment after you switch to landscape.  They should.  Then remove the setRetainInstance() call and re-run the program.  You will notice that the ids change every time you change the phone’s orientation.

 

Fragments are now considered the best practice for UI design on Android, and it’s easy to see why, since they offer a great deal of flexibility.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s