In today's Google mobile platform development ecosystem, the concept of modularity is the cornerstone of creating quality applications. One of the fundamental building blocks of this architecture is Fragment. It is not just a part of the user interface, but a complex, self-contained component with its own life cycle, which allows you to flexibly control the display of content on screens of various sizes.

Understanding what a fragment is and how it interacts with Activityis critical for any developer seeking to create responsive interfaces. Without the use of this technology, creating applications that work equally well on compact smartphones and spacious tablets would turn into a nightmare of code duplication and inefficient memory management.

In this article we will analyze in detail the internal structure of fragments, their types and features of interaction with host activity. We will also touch on optimization issues and common mistakes made when working with these components.

The essence and purpose of a Fragment

Fragment is a modular section of an activity that has its own layout, logic and life cycle. Essentially, it is a "piece" Activitythat can be reused in different contexts or combined with other pieces to create multi-panel interfaces.

The main purpose of using fragments is to increase the flexibility of the UI. For example, on a smartphone the application can display one fragment at a time (a list of articles), and on a tablet it can display two at once (a list of articles on the left and the contents of the selected article on the right). This is achieved without writing two completely different activities.

Developers often confuse fragments with regular ones View, but the difference is colossal. The fragment handles input events, has its own callback methods, and can be added to the navigation backstack. This makes them a powerful tool for building complex navigation within a single screen.

โš ๏ธ Attention: A fragment cannot exist independently. It must always be embedded within Activity or another fragment (nested fragments), otherwise the system will throw an exception when attempting to run.

Use FragmentManager allows fragments to be dynamically added, removed or replaced during app execution. This opens up opportunities for creating smooth transition animations and interactive interfaces that respond to user actions in real time.

๐Ÿ“Š Which navigation approach do you use more often?
One Activity + many Fragments
Many Activity
Jetpack Navigation Component
Legacy approach with Intent

Fragment life cycle

The life cycle of a fragment is closely related to the life cycle of its host activity, but has its own unique states. Understanding these states is necessary to properly allocate resources and prevent memory leaks. The main steps include attaching to an activity, creating a view, starting, and stopping.

When an activity receives an event onPause, all fragments associated with it also go into a paused state. This ensures that the state of the entire application is synchronized. However, a fragment has additional methods, such as onAttach and onDetach, that a regular activity does not have.

It is important to note the method onCreateView. This is where the initialization of the user interface occurs through inflating the XML layout. The returned object View becomes the root of the display hierarchy for this component. After finishing work with the view, it is called onDestroyView, which allows you to free up resources associated with the graphical interface, even if the fragment object itself is still alive.

The subtleties of the onSaveInstanceState method

The onSaveInstanceState method is called when the system plans to destroy the application process, but wants to save the state of the UI. Here you need to store primitive data types and Serializable objects, but not complex references to View or context.

Below is a table comparing the key lifecycle methods of an activity and fragment to better understand their relationship:

Event Activity method Method Fragment Description
Binding - onAttach Fragment associated with activity
Creation onCreate onCreate Initializing component logic
Creation UI setContentView onCreateView Inflating the interface layout
Start onStart onStart The component becomes visible
Unbinding - onDetach The fragment is detached from the activity

Sequence violation calls of super classes in these methods (for example, forgotten super.onCreateView) can lead to unstable operation of the application and system crashes Android Runtime.

Types of fragments and usage scenarios

Depending on the tasks being solved, fragments can be divided into several categories. Although technically they are all the same class androidx.fragment.app.Fragmentthe logic behind them is different.

List fragments are often used to display collections of data such as contacts or messages. They typically implement an interface RecyclerView.Adapter and handle clicks on list items by passing events to the parent activity.

Dialog fragments (DialogFragment) are used to create modal windows. Unlike the standard class AlertDialog, a dialog fragment behaves like a full-fledged component with a life cycle, which allows you to save its state when you rotate the screen or change the device configuration.

  • ๐Ÿ“ฑ Detail Fragment: Displays detailed information about the selected element (for example, the text of an article or a photo).
  • ๐Ÿ—‚๏ธ Master Fragment: Contains a list of elements for selection, often used in conjunction with Detail Fragment.
  • โš™๏ธ Settings Fragment: Implements the application settings screen, often inherited from PreferenceFragmentCompat.
  • ๐ŸŽจ UI Fragment: A purely visual component that does not contain complex business logic, used to reuse graphics.

Usage Child Fragments allows you to create even more complex interface hierarchies, when one fragment acts as a container for others. This is especially true for responsive layouts on tablets.

๐Ÿ’ก

Use the OnFragmentInteractionListener interface to safely pass data from a fragment to an activity, avoiding direct references to specific Activity classes.

Create and manage via FragmentManager

To work with fragments in the code, a special manager is used - FragmentManager. It is responsible for adding, removing, replacing and searching for fragments within an activity. In modern versions of Android, it is recommended to use support from the library AndroidX.

Transactions are performed through an object FragmentTransaction. You start a transaction, perform the necessary actions (for example, add or replace) and commit the changes using the commitmethod. It is important to understand the difference between adding and replacing: adding puts a new fragment on top of the old one, and replacing removes existing ones and inserts a new one.

FragmentTransaction transaction = getSupportFragmentManager.beginTransaction;

transaction.replace(R.id.fragment_container, new MyFragment);

transaction.addToBackStack(null);

transaction.commit;

Method addToBackStack plays a key role in navigation. It adds the transaction to the history stack, allowing the user to go back with the Back button, restoring the previous state of the fragment. Without this call, when you click "Back", the application will simply close if there are no other components left in the activity.

โš ๏ธ Warning: Never perform fragment transactions after onSaveInstanceState the activity. This will throw an exception IllegalStateExceptionas the state may be lost.

To search for a fragment by identifier or tag, the findFragmentById and findFragmentByTagmethods are used. This allows you to access public methods of a fragment from an activity or another fragment to coordinate their work.

Communication between components

One โ€‹โ€‹of the most difficult tasks when working with fragments is organizing data exchange between them. Directly calling one fragment to another is considered bad practice, as it violates the principle of modularity and complicates testing.

The correct approach is to use an intermediary activity or ViewModel from the Components architecture. Fragments send activity events, and an activity forwards data to another fragment. An alternative and more modern way is to use Shared ViewModelwhich belongs to the activity and is observed by both fragments.

When using callback interfaces, it is important to check whether the host activity implements the required interface in the method onAttach. If not, you should throw an exception early to avoid runtime errors. ClassCastException during execution.

โ˜‘๏ธ Secure Communication Checklist

Done: 0 / 4

The transfer of complex objects between fragments should be done via Bundle using the method setArguments. This ensures that the data will be correctly restored by the system when the fragment is recreated after the screen is rotated.

Common errors and optimization

Developers often encounter the problem of memory leaks when storing references to Context or View outside the life cycle of a fragment. For example, storing a reference to Context in a static field can prevent garbage collection for the entire activity.

Another common mistake is performing heavy operations in a method onCreateView. This causes the interface to slow down when scrolling through lists or switching tabs. All calculations must be carried out in separate threads or performed asynchronously.

  • โŒ Hardcoded ID: Using hard-coded IDs instead of arguments makes the fragment inflexible.
  • โŒ Direct Casting: Casting context to a specific activity without checking the interface.
  • โŒ AsyncTask inside Fragment: Running an AsyncTask that continues to run after onDestroyView.

For optimization It is recommended to use lazy data loading. This means that the data for a fragment is only loaded when it becomes visible to the user, not when it is created. This can be achieved by tracking methods setUserVisibleHint (in older versions) or using LifecycleObserver.

โš ๏ธ Attention: Android libraries and APIs are constantly updated. Methods described in legacy documentation (for example, support library v4) may differ from modern implementations in AndroidX. Always check the official Google guidelines.

๐Ÿ’ก

The main rule of optimization: A fragment should be as independent as possible and not know about the existence of other fragments, communicating with the world only through ViewModel or host interfaces.

FAQ: Frequently asked questions

What is the main difference between Activity and Fragment?

An Activity is a separate application screen with its own window, while a Fragment is just part of the interface inside an Activity. A Fragment cannot exist without an activity, has a simplified lifecycle and is designed for UI modularity.

Is it possible to use a Fragment without an XML layout?

Yes, it is possible. This fragment is called a โ€œfragment without UIโ€. It is used to perform background tasks, store state, or logic that needs to survive activity re-creation, but does not need to be displayed on the screen.

Why does an application crash with IllegalStateException when working with fragments?

Most often this happens due to an attempt to commit a transaction after the activity has saved its state (after onSaveInstanceState). Use commitAllowingStateLoss with caution or move the logic to an earlier stage in the lifecycle.

How to pass data from an Activity to a Fragment?

The best way is to use the setArguments(Bundle) method before adding the fragment. This ensures that data is preserved during configuration changes. Direct passing through a constructor or public fields is not recommended.

What is Child Fragment Manager?

This is a fragment manager that belongs to the fragment itself. It is needed to manage nested fragments (fragments within a fragment). Called through the method getChildFragmentManager.