What is Fragment?

Fragment = Fragment = Fragment Fragment represents a behavior or part of the interface in the FragmentActivity. You can combine fragments in a single Activity to build a multi-pane interface and reuse a fragment in multiple activities. A fragment can be thought of as a modular part of an Activity that has its own life cycle, can receive its own input events, and can be added or removed while the Activity is running (sort of like a “child Activity” that can be reused across different activities).

Fragments must always be hosted in the Activity, and their life cycle is directly affected by the host Activity life cycle. For example, when an Activity is paused, all fragments of the Activity are also paused; When an Activity is destroyed, all fragments are also destroyed.

However, while the Activity is running (in its resumed life cycle state), you can manipulate each fragment independently, such as adding or removing fragments. When such a fragment transaction is performed, it can also be added to the return stack managed by the Activity – each return stack entry in the Activity is a record of a fragment transaction that has occurred. With the back stack, the user can undo the fragment transaction (back) by pressing the back button.

The advantages of fragments

  • Fragment loading flexible, easy to replace. Customize your UI and create the right UI for different screen sizes to improve the user experience.
  • Reusable, page layouts can use multiple fragments, and different controls and content can be distributed on different fragments.
  • With fragments, you can use fewer activities. An Activity can host multiple fragments.

Fragment life cycle

The Fragment class code is very similar to an Activity. It contains callback methods similar to Activity, such as onCreate(), onStart(), onPause(), and onStop(). In fact, if you want to convert an existing Android application to use fragments, you might simply move the code from the Activity’s callback method into the corresponding callback method of the fragment.

In general, at least the following lifecycle methods should be implemented:

  • The onCreate() system calls this method 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 implementation.
  • The onCreateView() system calls this method when the fragment first draws its interface. To draw an interface for a fragment, the View returned from this method must be the root View of the fragment layout. Null can be returned if the fragment does not provide an interface.
  • The onPause() system calls this method as the first signal that the user is leaving the fragment (but does not always mean that the fragment will be destroyed). In general, this method should validate any changes that remain in effect after the end of the current user session (because the user may not return).

You might also want to extend several subclasses instead of the Fragment base class:

  • DialogFragment Displays a floating dialog box. Using this class to create dialog boxes is a useful alternative to using dialog assist methods in the Activity class, because you can place fragment dialog boxes on the fragment return stack managed by the Activity, enabling the user to return to the cleared fragment.
  • ListFragment displays a list of items managed by an adapter such as SimpleCursorAdapter, similar to ListActivity. This class provides several ways to manage list views, such as the onListItemClick() callback for handling click events. Note that the preferred way to display lists is to use RecyclerView rather than ListView. In this case, create a fragment that contains RecyclerView in the list layout. For details, see Creating lists using RecyclerView.)
  • PreferenceFragmentCompat displays the hierarchy of Preference objects as a list. This class is used to create the Settings screen for the application.
Create fragments and use the custom interface

Fragments are usually used as part of the Activity interface and incorporate their own layout into the Activity.

To provide a layout for a fragment, you must implement the onCreateView() callback method, which the Android system calls when the fragment needs to draw its layout. The View returned by the implementation of this method must be the root View of the fragment layout.

To return the layout from onCreateView(), you can extend the layout with layout resources defined in the XML. To help you do this, onCreateView() provides a LayoutInflater object.

For example, the following Fragment subclass loads the layout from the example_fragment.xml file:

public static class ExampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); }}Copy the code

The container argument passed to onCreateView() is the parent ViewGroup (from the Activity’s layout) into which the fragment layout will be inserted. The savedInstanceState parameter is the Bundle that provides data related to the previous fragment instance when a fragment is restored (the recovery state is explained in detail in the section dealing with the fragment lifecycle).

The inflate() method takes three parameters:

  • The resource ID of the layout you want to expand.
  • The ViewGroup that will be the parent of the extended layout. Passing Containers is important for the system to apply layout parameters to the root view of the extended layout, specified by the parent view to which it belongs.
  • Indicates whether the extension layout should be appended to the Boolean value of the ViewGroup (second argument) during the extension. (In this case, the value is false because the system has inserted the extension layout into the Container, and passing true creates an unnecessary view group in the final layout.)

Next, you need to add this section to your Activity.

Add a Fragment to the Activity

Typically, fragments contribute a portion of the interface to the host Activity, embedded in the Activity as part of the overall view hierarchy of the Activity. You can add fragments to the Activity layout in two ways (the code snippets below are not the full code).

The static way

Declare the fragment in the Activity’s layout file. In this case, you can specify layout properties for the fragment as if it were a view. For example, here is the layout file for an Activity with two fragments:

<? The 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.

When you create the Activity layout, the system instantiates each fragment specified in the layout and calls the onCreateView() method for each fragment to retrieve the layout for each fragment. The system inserts the View returned by the fragment directly instead of the

element.

Note: Each fragment requires a unique identifier that can be used by the system to recover the fragment when restarting the Activity (or to capture the fragment to perform certain transactions, such as removing it). You can provide an ID for a fragment in two ways: provide a unique ID for the Android: ID attribute. Provides a unique string for the Android: Tag attribute.

Java code loads fragments

Alternatively, you can programmatically add fragments to an existing ViewGroup. You can add fragments to the Activity layout at any time while the Activity is running. You simply specify which ViewGroup to place the fragment in.

To perform fragment transactions (such as adding, removing, or replacing fragments) within an Activity, you must use the API in FragmentTransaction. You can get a FragmentTransaction instance from FragmentActivity as follows:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Copy the code

You can then add a fragment using the add() method, specifying which fragment to add and which view to insert it into. Such as:

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Copy the code

The first argument passed to add() is the ViewGroup, where the fragment should be placed, specified by the resource ID, and the second argument is the fragment to add. Once a change has been made via FragmentTransaction, commit() must be called for the change to take effect.

Management of fragments

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

Actions that can be performed using FragmentManager include:

  • throughfindFragmentById()(for fragments that provide an interface in the Activity layout) or findFragmentByTag() (for fragments that provide or don’t provide an interface) gets the fragments that exist in the Activity.
  • throughpopBackStack()(mimics a return command issued by the user) pops the fragment from the return stack.
  • throughaddOnBackStackChangedListener()Register a listener to listen for changes in the return stack.

You can also open a FragmentTransaction using the FragmentManager to perform certain transactions, such as adding and removing fragments.

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, and one transaction can be executed using the API in FragmentTransaction. You can also save each transaction to a back stack managed by the Activity, allowing the user to roll back fragment changes (similar to rolling back an Activity).

You can get a FragmentTransaction instance from the FragmentManager as follows:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Copy the code

Each transaction is a set of changes that you want to execute simultaneously. You can use methods like add(), remove(), and replace() to set 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.

For example, the following example shows how to replace one fragment with another and how to preserve the previous state in the return stack:

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();
Copy the code

In this case, newFragment replaces any fragments (if any) in the layout container currently identified by the R.I.D.Fragment_container ID. By calling addToBackStack(), the replacement transaction can be saved to the back stack so that the user can undo the transaction and fall back to the previous fragment by pressing the back button.

The FragmentActivity then automatically retrieves the fragment from the return stack via onBackPressed().

If you add multiple changes to a transaction (such as another add() or remove()) and call addToBackStack(), all the changes applied before the commit() call are added to the return stack as a single transaction, and the back button undoes them altogether.

The order in which changes are added to FragmentTransaction is irrelevant, but:

You must finally call commit(). If multiple fragments are added to the same container, the order in which they are added will determine the order in which they appear in the view hierarchy. If addToBackStack() is not called when the transaction that deletes the fragment is executed, the segment is destroyed when the transaction commits and the user cannot fall back to it. However, if addToBackStack() is called when the fragment is deleted, the system stops the fragment and then restores it when the user falls back.

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.

Note: Use commit() to commit a transaction only 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().

Life cycle change

When the Fragment is created

It goes through the following states

onAttach()
onCreate()
onCreateView()
onActivityCreated()
Copy the code

Fragment is visible to the user

It goes through the following states

onStart()
onResume()
Copy the code

Fragment enters background mode

It goes through the following states

onPause()
onStop()
Copy the code

Fragment was destroyed (or the activity holding it was destroyed)

It goes through the following states

onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()
Copy the code

Fragment and Activity have different life cycles

Most of the states of a Fragment are similar to those of an Activity, but a Fragment has some new states.

Fragments are different from the Activity lifecycle – onAttached() – called when the Fragment is added to the Activity (you can get the Activity in this method). -onCreateView () — This method is called when the activity wants to get a layout for the fragment that creates its own layout. – onActivityCreated() — called when the activity’s onCreated() method returns. – onDestroyView() — called when the view in the fragment has been removed. -ondetach () — This method is called when the fragment and activity are separated.

Once your activity is in its resumed state, you can add and remove fragments freely. Therefore, the fragment’s life cycle can run independently only if the activity is in a resumed state; otherwise, it depends on the activity’s life cycle.

Process the Fragment life cycle

Managing the fragment life cycle is similar to managing the Activity life cycle. Like activities, fragments exist in three states:

  • Recovered: The 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. As with activities, you can use a combination of onSaveInstanceState(Bundle), ViewModel, and persistent local storage to preserve the interface state of the fragment after configuration changes and process terminations. For more information about preserving interface state, see Saving Interface State.

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, an Activity is put into the system-managed Activity return stack when it stops. However, fragments are placed on the return stack managed by the host Activity only when an explicit request to save the instance is made by calling addToBackStack() during the transaction that removes the fragment.

In other respects, managing the fragment life cycle is very similar to managing the Activity life cycle; The same can be done for this.

Note: If a Context object is needed in your Fragment, you can call getContext(). Note, however, that you only need to call getContext() if the segment is attached to the Activity. GetContext () returns NULL if the segment has not been attached, or if it has been detached at the end of its life cycle.

Fragment: Fragment

1. How to Toggle Fragement (without reinstantiating)

Taking a look at the Android Doc and some of the component source code, replace() is just a handy method to use when the previous Fragment is no longer needed.

The correct way to switch is to add(), hide(), add() another Fragment; To switch again, simply hide() the current and show() the other. This allows you to switch multiple fragments without re-instantiating them:

2. The advantages of Fragment

  • Fragments enable you to split an activity into multiple reusable components, each with its own life cycle and UI.
  • Fragments make it easy to create dynamic and flexible UI designs that can be adapted to different screen sizes. From phones to tablets.
  • Fragment is a separate module that is tightly tied to an activity. Can dynamically remove, add, swap, etc.
  • Fragment offers a new way to unify your UI across different Android devices.
  • Fragment Solve the switching between activities is not smooth, light switching.
  • Fragment replaces TabActivity for navigation with better performance.
  • Fragment has been added in 4.2. Version to generate better interface effect.

3. How does Fragment achieve the effect of Activity stack pressing and discharging

The Fragment transaction manager maintains a two-way linked list structure that records every Fragment we add and replace, and then automatically destacks us when we click the back button.

4. The difference between replace and add methods of fragments

The Fragment itself does not have replace and add methods. The difference between using the replace and add methods of the FragmentManager to switch the Fragment is not obvious.

One architecture we often use is to toggle fragments through radiogroups, where each Fragment is a functional module.

Fragment container a FrameLayout. Add all fragments layer by layer to FrameLayout. Replace first removes other fragments from the container and then adds the current Fragment to the container.

Only one Fragment type can be added to a Fragment container. If you add more than one Fragment type, an exception will be raised and the program will terminate. Replace does not matter.

Since each Fragment added by add can be added only once, you need to use the hide and show methods of the Fragment to switch between them. Show to be displayed, hide the rest. The life cycle of this process Fragment does not change. When replacing a Fragment, the onDestroyView of the previous Fragment is executed each time, and the onCreateView, onStart, and onResume methods of the new Fragment are executed.

Based on the above different characteristics, we must use our view and data in conjunction with the life cycle.

5. How to transmit values between Fragments and activities

  • Activity passes values to fragments:

The values that are going to be passed into the bundle object; Create an object Fragment for that Fragment in your Activity,

Pass this to the fragment by calling fragment.setarguments (); Get the bundle object in that Fragment by calling getArguments(), and you can get the values inside.

  • Fragment sends a value to an Activity:

Call getFragmentManager() in your Activity to get the fragmentManager,, Call findFragmentByTag(tag) or findFragmentById(ID) FragmentManager FragmentManager = getFragmentManager(); Fragments fragments = fragmentManager. FindFragmentByTag (tag);

Using a callback to define an interface (you can define it in the Fragment class) with an empty method in the Fragment class. Call the interface’s method when needed and place the value as a parameter in the Fragment method. Then let the Activity implement the interface, which must override the method. The value is then passed into the Activity.

Fragment life cycle

  • OnAttach (Contextcontext) : called only once when the Fragment is associated with the Activity. In this callback, we can convert the context to an Activity and save it from calling the getAtivity() ativity too often to fetch the Activity. Avoid exceptions where getAtivity() is empty in some cases (in the case of Activity and Fragment separation). You can also extract and parse Arguments passed in this callback, and here it’s highly recommended to pass parameters to Fragment via setArguments, because Fragment doesn’t hold the properties when the app is retracted by the system.

  • OnCreate: Called when the Fragment is initially created, similar to the onCreate of an Activity.

  • View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) : Called when the Fragment interface is ready to draw, and returns the root view of the layout that the Fragment is drawing, or null. When inflater is used to build views, set attachToRoot to false because the Fragment automatically adds views to the Container. When attachToRoot is true, it repeatedly adds an error. OnCreateView is not always called. It is not called when adding a Fragment that has no interface, such as when calling the Add (Fragment Fragment, String Tag) method for FragmentTransaction.

  • OnActivityCreated: called when the Activity’s onCreated completes.

  • OnStart () : Called when the Fragment is visible to the user, if the Activity is already started.

  • OnResume () : Called before the Fragment can interact with the user, if the Activity is resumed.

  • OnPause () : called when the Fragment cannot interact with the user before.

  • OnStop () : called when Fragment is not visible.

  • OnDestroyView () : Called when removing the fragment-related view hierarchy.

  • OnDestroy () : called when the Fragment state is finally clear.

  • OnDetach () : called when Fragment and Activity are disassociated.

7. The impact of ViewPager on the Fragment lifecycle

ViewPager + fragments is the combination of the more common, general collocation ViewPager FragmentPagerAdapter or FragmentStatePagerAdapter use. However, ViewPager has a caching mechanism to prevent slippage. By default, ViewPager creates and caches pages (such as fragments) on the left and right sides of the current page. OnAttach ->… -> Life cycle of onResume, the Fragment is not displayed but is already in onResume, there is a problem in some cases. For example, the loading time of data, whether the Fragment is visible, etc.

Android zero introductory tutorial video reference: https://www.bilibili.com/video/BV19r4y117cF?spm_id_from=333.999.0.0)Copy the code