An overview of

Fragment represents a behavior or part of the interface in the FragmentActivity.

Android introduced snippets in Android 3.0 (API level 11) with the primary purpose of enabling more dynamic and flexible interface design on large screens such as tablets. Because tablets’ screens are much bigger than phones’, there is more room to combine and swap interface components. When you implement this kind of design with fragments, you don’t have to manage complex changes to the view hierarchy. By breaking the Activity layout into fragments, you can modify the appearance of the Activity at run time and keep those changes in the back stack managed by the Activity.

Each fragment should be designed as a reusable modular Activity component. In other words, because each fragment defines its own layout and behavior through its own lifecycle callbacks, a fragment can be added to multiple activities, so you should use a reusable design to avoid directly manipulating one fragment through another.

Fragments must always be hosted in the Activity, and their life cycle is directly affected by the host Activity life cycle.

The life cycle

Life cycle phases

The classic life cycle diagram:

  • onAttach(Context context)

Called when the fragment is already associated with the Activity (the Activity is passed into this method).

  • onCreate(Bundle savedInstanceState)

This method is called when the fragment is created. If you want to preserve the basic components of a fragment after it has gone through a paused or stopped state and then resumed, you should initialize it in the concrete implementation.

  • onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

This method is called when the fragment first draws its interface. To draw an interface for a fragment, the View returned in this method must be the root View of the fragment layout. Null can be returned if the fragment does not provide an interface.

  • onActivityCreated(Bundle savedInstanceState)

Called when the Activity’s onCreate() method has returned.

  • OnStart (), onResume(), onPause(), onStop()

With the Activity

  • onDestroyView()

Called when the view hierarchy associated with the fragment is removed.

  • onDestroy()

Called when the fragment is no longer in use.

  • onDetach()

Called when a fragment is unassociated with an Activity.

Impact of the Activity life cycle on the Fragment life cycle

Managing the fragment life cycle is similar to managing the Activity life cycle. The life cycle of the Activity in which the fragment is located directly affects the life cycle of the fragment in that each lifecycle callback of the Activity triggers a similar callback for each fragment. For example, when an Activity receives onPause(), each fragment of the Activity also receives onPause().

Like activities, fragments exist in three states:

  • The recovered fragment is visible in the running Activity.
  • Paused Another Activity is in the foreground and has focus, but the Activity in which the fragment is located is still visible (the foreground Activity is partially transparent, or does not cover the entire screen).
  • Stopped fragments are not visible. The host Activity has been stopped, or the fragment has been removed from the Activity but added to the back stack. Stopped fragments are still active (the system retains all state and membership information). However, it is no longer visible to the user and terminates when the Activity terminates.

The most significant difference between the Activity life cycle and the fragment life cycle is the way they are stored in their respective return stacks. By default, when an Activity stops, it is placed in the system-managed Activity return stack; However, the system only places the fragment on the return stack managed by the host Activity if an explicit request to save the instance is made by calling addToBackStack() during the transaction that removes the fragment.

Fragment creation and management

create

Overwrite onCreateView from base Fragment class to provide content layout.

Or inherit the Android system’s built-in Frament with special properties :DialogFragment (display floating dialog), ListFragment (display a list of items managed by an adapter (such as SimpleCursorAdapter), Similar to ListActivity), PreferenceFragmentCompat (displaying a hierarchy of Preference objects as a list)

Add a Fragment to the Activity

  • Declare the fragment in the Activity’s layout file
<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>
Copy the code

The Android: Name attribute in < Fragment > specifies the fragment class to instantiate in the layout.

  • Programmatically add a fragment to an existing ViewGroup
val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() val fragment =  ExampleFragment() fragmentTransaction.add(R.id.fragment_container, Fragments) / / you must call commit the operation effect fragmentTransaction.com MIT ()Copy the code

Uniquely identified Fragment

  • Id: Provides a unique ID.
  • Tag: provides a unique string.

Management of fragments

To manage fragments in an Activity, use FragmentManager. If you want to get it from the Activity call getSupportFragmentManager ().

The operations that can be performed include:

  • FindFragmentById () or findFragmentByTag() gets the fragment that exists in the Activity.
  • Pop the fragment from the return stack by popBackStack(), which simulates a return command issued by the user.
  • Through addOnBackStackChangedListener () registered listener listener return stack changes.

Executing a Fragment transaction

One advantage of using fragments in an Activity is that you can respond to user interactions by adding, removing, replacing, and other actions through fragments. Each set of changes submitted to the Activity is called a transaction. Each transaction is a set of changes that you want to execute simultaneously. You can use methods like add(), remove(), and replace() to set up all the changes you want to perform for a given transaction. Then, to apply a transaction to the Activity, you must call commit().

However, before calling commit(), you might want to call addToBackStack() to add the transaction to the fragment transaction return stack. This back stack is managed by the Activity and allows the user to return to the previous fragment state by pressing the back button.

val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val newFragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, newFragment)
transaction.addToBackStack(null)
transaction.commit()
Copy the code

Calling commit() does not execute the transaction immediately, but instead schedules the transaction to run on the Activity’s interface thread (the “main” thread) when it is ready to perform the operation. However, if necessary, can also from the UI thread calls executePendingTransactions (), to immediately implement the commit () committed transaction. This is usually not necessary unless jobs in other threads depend on the transaction.

commitAllowingStateLoss()

When doing a Fragment transaction, you can only commit the transaction with commit() before the Activity saves its state (when the user leaves the Activity). If you try to commit after that point, an exception is thrown. This is because the state after submission may be lost if the Activity needs to be resumed. For lost commits that don’t matter, use commitAllowingStateLoss().

Communicate with the Activity

Although a Fragment is implemented as a separate object from a FragmentActivity and can be used within multiple activities, a given instance of the Fragment is directly bound to the Activity hosting the Fragment.

A fragment can access an instance of FragmentActivity with getActivity() and easily perform tasks such as finding views in the Activity layout; An Activity can also use findFragmentById() or findFragmentByTag() to call methods in fragments by getting a reference to the Fragment from the FragmentManager.

In some cases, you may need to use fragments to share events or data with the Activity and/or other fragments hosted by the Activity. At this point, you define a callback interface within the fragment and require the host Activity to implement it.

Add and replace for Fragment transactions

There are two ways to switch fragments

  • Use replace to switch directly
  • Use add to add the Fragment, use hide to hide the Fragment that is not displayed, and use show to display the Fragment that needs to be displayed

Add adds the life cycle of the Fragment when it is called

The life cycle of a call to replace to switch fragments

As you can see, replace executes the entire life cycle each time, and if the data is pulled from these life cycle functions, it will repeatedly load and refresh the data.

About the add

Add (r.d.fragment_container, oneFragment).hide(twoFragment).commit();

  • The first parameter is the id of the container. The second parameter is the fragment to be added. Adding the fragment does not empty the contents of the container.
  • Adding the same Fragment instance is not allowed, which is an important feature. If a fragment has already been added, adding it again will cause an exception error.
  • Any added fragment is visible. The last fragment is displayed on top of the first one. All visible views are drawn when the interface is drawn.
  • So most add is used with hide or remove. This method is recommended to save the time of drawing the interface and memory consumption.

About the replace

transaction.replace(R.id.fragment_container, oneFragment).commit();

  • Substitution replaces everything in the container. Some apps use this method to keep only one fragment displayed, reducing the hierarchy of the interface.

Reasonable use plan

  • In general, if there are not many fragments, add can be used to switch, which can improve the efficiency of switching and ensure the smoothness of app (space for time).
  • If there are many fragments and high memory requirements, replace will be used to ensure that the APP will not run out of memory (time for space).