This is the first day of my participation in Gwen Challenge

Like attention, no more lost, your support means a lot to me!

🔥 Hi, I’m Chouchou. GitHub · Android-Notebook has been included in this article. Welcome to grow up with Chouchou Peng. (Contact information at GitHub)


preface

  • Fragment is a component with a long history. Introduced in API 11, Fragment has become one of the most commonly used components in Android development.
  • In this topic, we will discuss fragments at three levels: using & Core Principles & Interviewing. Please be sure to like and follow if you can help, it really means a lot to me.

directory


Fragment past, present and future

1.1 What problems does Fragment solve? (the past)

Fragment can split the Activity view into multiple blocks for modular management, avoiding excessive bloated and chaotic Activity view code. While custom Views or Windows can split the Activity interface to a certain extent, they actually do different things: View/Window encapsulates some View functionality, while Fragment uses control to customize the View at a higher level. In addition, fragments make it easier to manage life cycles and transactions (although we separate the business logic through MVP or MVVM patterns, for complex pages, we can’t avoid the Activity view code evolving very bloated and messy).

Note that a Fragment cannot exist independently of an Activity. It must be hosted by either the Activity or another Fragment. Views instantiated by Fragment#onCreateView will eventually be embedded in the host’s view tree.

class role The MVVM layered Life cycle perception
Activity View controller The View layer perception
Fragment View controller The View layer perception
View view The View layer Don’t perceive
Window view The View layer Don’t perceive

1.2 What are the problems with Fragments? (now)

Fragment was originally designed to act as a “mini-activity”. As the saying goes, “If you want to wear the crown, it must be heavy.” Many apis designed specifically for activities also need to be added to the Fragment, such as new apis for runtime permissions and multi-window mode switching. This extends the boundaries of a Fragment’s responsibilities and increases the complexity of its design, given that the essence of a Fragment is interface modularity.

1.3 Fragment 2.0

Google is rethinking the position of the Fragment. The new version of the Fragment is coming to our attention with the update of AndroidX Fragment. We call the new version of the Fragment 2.0.

  • FragmentScenario: a testing framework for fragments;
  • FragmentFactory: a unified Fragment instantiation component;
  • FragmentContainerView: Fragment view container;
  • OnBackPressedDispatcher: Handles the return button event in a Fragment or other component.

Concrete analysis see: Android | get in the car! AndroidX Fragment new pose!


2. Talk about the overall structure of fragments

Now, we will start to discuss the core working principles of Fragments. During the analysis process, I will read the source code to help you understand the working principles of fragments more clearly and comprehensively. However, before we begin, it is necessary to review the overall structure of the Fragment source code to lay a foundation for further reading of the source code.

2.1 Code Framework

FragmentActivity.java

final FragmentController mFragments = FragmentController.createController(new HostCallbacks()); protected void onCreate(@Nullable Bundle savedInstanceState) { mFragments.attachHost(null /*parent*/); super.onCreate(savedInstanceState); . / / FragmentController defines many dispatchXX mFragments () method. The dispatchCreate (); }Copy the code

The following UML class diagram describes Framgent’s overall code framework:

The main points are as follows:

  • FragmentActivity is the basis for activities that support fragments. It holds a middle class called FragmentController, which acts as a bridge between FragmentActivity and FragmentManager. Operations on fragments are ultimately distributed to the FragmentManager for processing;

  • The FragmentManager hosts the core logic of the Fragment and is responsible for adding, removing, or replacing the Fragment, as well as adding to the return stack. Its implementation class, FragmentManagerImpl, is our primary analysis object;

  • FragmentHostCallback is the FragmentManager callback interface to the Fragment host. Both activities and Fragments have internal classes that implement this interface. So both an Activity and a Fragment can host another Fragment (the Fragment host and FragmentManager are 1:1).

  • FragmentTransaction is a Fragment transaction abstraction class, and its implementation class BackStackRecord is the main analysis object for transaction management.

The following diagram depicts each host’s relationship to the associated FragmentManager:

Tip (must see) : In this discussion, we will no longer perceive the FragmentController between FragmentActivity and Fragment, because this is an implementation detail of the software design pattern, not the Fragment’s core source code. Read the source code we must remove the surface to see the essence, grasp the process, do not get bogged down in details.

2.2 What is the Fragment life cycle?

Life cycle awareness is one of the most basic functions of fragments and is a critical area for interviews. I think it would be better to explain your understanding of the following questions before the “recitation” life cycle:

  • Question 1: What is a lifecycle, and are lifecycle callback methods (such as onCreateView()) the nature of the lifecycle?

Answer: No. State transitions are the essence of the lifecycle (the same goes for activities). The essence of a lifecycle method is a Fragment state transition. When a lifecycle method is called, it means that the Fragment moves from one state to another. The so-called “lifecycle callback” is just a Hook point provided by the Framework for developers to use. Used to perform custom logic during state transitions.

  • Question2: You mentioned state transition, what states are there in the Fragment?

A: AndroidX Fragment defines the following five states from the source code. Compared to the earlier Support Fragment version, there are fewer states such as STOPPED, because Google thinks these states can be used symmetrically. For example, STOPPED and STARTED states are essentially the same.

Fragment.java

static final int INITIALIZING = 0; Static final int CREATED = 1; static final int CREATED = 1; Static final int ACTIVITY_CREATED = 2 static final int ACTIVITY_CREATED = 2 Static final int STARTED = 3 static final int STARTED = 3 Static final int RESUMED = 4; Foreground state that accepts user interactionCopy the code
  • Question 3: Is the Fragment life cycle synchronized with the host? If not, is it independent?

Answer: No. The Fragment life cycle is mainly influenced by three factors: host, transaction, and setRetainInstance() API. When the host life cycle changes, the Fragment state is triggered to move to the latest state of the host. However, using transactions and the setRetainInstance() API can also make the Fragment somewhat out of sync with the host state (note: the host is still somewhat constrained).

  • Host: [see section 3]
  • Transactions: [see section 4]
  • SetRetainInstance () API:

The Fragment life cycle is completely illustrated in the following diagram:

— Picture quoted from Internet

It’s a lot. Don’t be afraid. Just follow my lead and that’s it: “That’s it? 🙇”


3. How does the host change the Fragment state

As mentioned earlier, the Fragment life cycle is influenced by three factors, but let’s discuss the host factor for a moment.

3.1 Synchronization relationship between Activity and Fragment life cycles

When the host life cycle changes, the Fragment state is synchronized to the host state. From the source code, a series of dispatchXXX() methods in the FragmentManager are called in the host lifecycle callback to trigger Fragment state transitions.

FragmentActivity

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { mFragments.attachHost(null /*parent*/); . mFragments.dispatchCreate(); // Finally call FragmentManager#dispatchCreate()}Copy the code

The following table summarizes the relationship between the Activity lifecycle and the Fragment lifecycle:

Activity Lifecycle FragmentManager Fragment State Transfer Fragment life cycle callback
onCreate dispatchCreate INITIALIZING

-> CREATE
-> onAttach

-> onCreate
OnStart (First time) dispatchActivityCreated

dispatchStart
CREATE

-> ACTIVITY_CREATED

-> STARTED
-> onCreateView

-> onViewCreated

-> onActivityCreated

-> onStart
OnStart (not first-time) dispatchStart ACTIVITY_CREATED

-> STARTED
-> onStart
onResume dispatchResume STARTED

-> RESUMED (Fragment)
-> onResume
onPause dispatchPause RESUMED

-> STARTED
-> onPause
onStop dispatchStop STARTED

-> ACTIVITY_CREATED
-> onStop
onDestroy dispatchDestroy ACTIVITY_CREATED

-> CREATED

-> INITIALIZING
-> onDestroyView

-> onDestroy

-> onDetach

3.2 State transfer core source code analysis

A series of dispatchXXX() methods in FragmentManager trigger Fragment state transitions.

Tip: Source code methods jump too much to understand the core flow. I’ll tease out the core process for you, which is different from looking at the source code, but the logic is the same.

FragmentManager.java

Public void dispatchCreate() {mStateSaved = false; mStopped = false; moveToState(Fragment.CREATED, false); 4. Handle outstanding transactions (see section 4) execPendingActions() } void moveToState(int newState, Boolean always) {return (nextState == mCurState); } mCurState = nextState; // Must add them in the proper order. MActive fragments may be out of order for (int I = 0; i < mAdded.size(); i++) { Fragment f = mAdded.get(i); / / update the fragments to the current state of moveFragmentToExpectedState (f); } 3, execute not add, But ready to remove Fragment // Now iterate through all active fragments. These will include those that are removed and detached. for (int i = 0; i < mActive.size(); i++) { Fragment f = mActive.valueAt(i); if (f ! = null && (f.mRemoving || f.mDetached) && ! F. may IsNewlyAdded) {/ / update the fragments to the current state moveFragmentToExpectedState (f); }}}Copy the code

Among them, the moveFragmentToExpectedState () call to moveToState eventually (fragments, int) :

FragmentManager.java

- > moveFragmentToExpectedState final call to fragments - > updates to the current state of void moveToState (fragments f, Int newState) {1, create Detatch Fragment if ((! f.mAdded || f.mDetached) && newState > Fragment.CREATED) { newState = Fragment.CREATED; } if (f.removing && newState > f.state) {if (f.i.sinbackstack ()) {2.1 Add the remove action to the return stack. NewState = math. min(nextState, fragment.created); } else {2.1 DESTROY newState = math.min (nextState, fragment.initializing); If (f.state <= newState) {switch (f.state) {case fragmenting.INITIALIZING: if (nextState> Fragment.INITIALIZING) { ... } // fall through case Fragment.CREATED: ... // fall through case Fragment.ACTIVITY_CREATED: ... // fall through case Fragment.STARTED: ... } } else { switch (f.mState) { case Fragment.RESUMED: if (newState < Fragment.RESUMED) { ... } // fall through case Fragment.STARTED: ... // fall through case Fragment.ACTIVITY_CREATED: ... // fall through case Fragment.CREATED: ... }}... }Copy the code

The above code has been very simplified, to sum up:

When state transition is triggered, the Fragment is judged first. If it is already in the target state newState, the state transition is skipped. However, not all fragments in the FragmentManager will perform state transitions. Only fragments with “mAdded as true && mDetached as false” will update to the target state, and the rest will leave the host state. Finally, unexecuted transactions execPendingActions() are processed after the state transition is complete; Each dispatchXXX() provides a window for transaction execution.

The relationship between the different fragments flag bits (Detach/Remove/return stack) and the final state is summarized in the following table:

situation judge describe A final state
1 f.mRemoving remove Fragment.INITIALIZING
2 f.mRemoving && f.isInBackStack() Remove, but add to return stack Fragment.CREATED
3 ! f.mAdded || f.mDetached Did not add Fragment.CREATED
4 f.mAdded Have been added NewState (sync to host state)

Tip: These flag bits can interfere with transactions.

3.3 Life Cycle of Typical Scenarios

Basic rule: Activity state transfer Triggers Fragment state transfer.

First startup:  Activity - onCreate Fragment - onAttach Fragment - onCreate Fragment - onCreateView Fragment - onViewCreated Activity -  onStart Fragment - onActivityCreated Fragment - onStart Activity - onResume Fragment - onResume -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- exit:  Activity - onPause Fragment - onPause Activity - onStop Fragment - onStop Activity - onDestroy Fragment - onDestroyView Fragments - onDestroy fragments - onDetach -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- back to the desktop:  Activity - onPause Fragment - onPause Activity - onStop Fragment - onStop -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- return:  Activity - onStart Fragment - onStart Activity - onResume Fragment - onResumeCopy the code

4. Fragment transaction management

Now, let’s discuss the second factor that affects Fragment state transitions: transactions.

4.1 Transaction Overview

  • Question 1: What is the nature of transactions? Transactions are the basic unit of recovery and concurrency and have four basic features:

    • Atomicity: transactions are indivisible and either all complete or all fail and roll back;
    • Consistency: Data is consistent before and after transaction execution;
    • Isolation: no interference from other transactions during transaction execution;
    • Persistence: Once a transaction completes, changes to data are permanent. After the Fragment state is saved in Android, the commit() transaction throws an exception, because the state affected by the newly committed transaction cannot be saved.
  • The FragmentTransaction can be used to dynamically change the Fragment state, leaving the Fragment somewhat out of the host state. However, transactions are still constrained by the host state. For example, if the Activity is currently in the STARTED state, addFragment does not cause the Fragment to RESUME. The Activity is synchronized to the latest state only when it resumes in the future.

4.2 Do you know the difference between different transaction operations?

  • Add & remove: Fragment state between INITIALIZING and RESUMED;
  • Detach & attach: The Fragment state is transferred between CREATE and RESUMED;
  • Replace: Remove all instances of containerId and add a Fragment.
  • Show & hide: Controls only the Fragment to hide or display, does not trigger state transitions, and does not destroy the Fragment view or instance.
  • The difference between hide and detach and remove is that hide does not destroy views and instances, detach only destroys views and does not destroy instances, and Remove destroys instances (as well as views). However, if a transaction is added to the rollback stack while removing, the Fragment instance is not destroyed, only the view is destroyed.

The following diagram illustrates the simple relationship between Fragment state transitions and hosts and transactions:

One of the confusing issues here is that the Detach Fragment does not call back onDetach() because detach only moves to the CREATE state, whereas the callback onDetach() needs to move to INITIALIZING. I wonder why Google chose such an ambiguous name.

Detach Fragment: fragment-onpause fragment-onStop fragment-onDestroyViewCopy the code

4.3 What is the difference between different transaction submission modes?

FragmentTransaction defines five types of commit:

API describe Whether the synchronization
commit() Commit transactions asynchronously with no loss of state asynchronous
commitAllowingStateLoss() Commit transactions asynchronously, allowing state loss asynchronous
commitNow() Commit transactions synchronously with no loss of state synchronous
commitNowAllowingStateLoss() Commit transactions synchronously, allowing state loss synchronous
executePendingTransactions() Synchronously execute all transactions in the transaction queue synchronous

Points to note:

  • After onSaveInstanceState() saves the state, the new state created by the transaction is not saved. Calling commit() or commitNow() after the state is saved throws an exception

FragmentManagerImpl.java

private void checkStateLoss() { if (mStateSaved || mStopped) { throw new IllegalStateException("Can not perform this action after onSaveInstanceState"); }}Copy the code
  • Use commitNow () or commitNowAllowingStateLoss () committed transaction is not allowed to join the back stack

Why this design? It is possible that Google simply forbids commitNow() from being added to the rollback stack, considering that both synchronous and asynchronous commit transactions exist, and that it is not possible to determine which is expected when both transactions are added to the rollback stack. If really have the need to synchronize the + back stack application scenarios, can use the commit () + executePendingTransactions short-cut method (). The relevant source code is as follows:

BackStackRecord.java

@Override
public void commitNow() {
    disallowAddToBackStack();
    mManager.execSingleAction(this, false);
}

@Override
public void commitNowAllowingStateLoss() {
    disallowAddToBackStack();
    mManager.execSingleAction(this, true);
}
@NonNull
public FragmentTransaction disallowAddToBackStack() {
    if (mAddToBackStack) {
        throw new IllegalStateException("This transaction is already being added to the back stack");
    }
    mAllowAddToBackStack = false;
    return this;
}    
Copy the code
  • CommitNow () and executePendingTransactions () are performed synchronously, is there a difference?

CommitNow () is the simultaneous execution of the current transaction, and executePendingTransactions () is a synchronous perform transactions in the queue all transactions.


5. How to load the Fragment into the interface?

5.1 Adding Methods

There are two ways to add a Fragment to an Activity view: statically loading + dynamically loading

  • Static loading: Static loading refers to the use of tags to add fragments to the layout file. Summary:
attribute describe
class Fully qualified class name of Fragment
android:name Fully qualified Fragment class name (same as class, but class takes precedence)
android:id Fragment unique identifier
android:tag Fragment unique identifier (at least one ID and tag)

For example:

<? 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.TestFragmentFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>Copy the code
  • Dynamic loading: Dynamic loading refers to the way you add fragments to your code using the FragmentTransaction. Such as:
TextFragment fragment = new TextFragment();
fragmentTransaction.add(R.id.containerId, fragment);
fragmentTransaction.commit();
Copy the code

5.2 Fragment Static loading source code analysis

Adding fragments from layout files is essentially the process of parsing XML into a view tree, which is done by LayoutInflaters. Finally, tag parsing is ultimately handed over to FragmentManager#onCreateView(…). Processing, let’s take a look at the specific how to process, the source code is as follows:

FragmentManagerImpl.java

Public View onCreateView(@nullable View parent, @nonNULL String name, @nonnull Context, @nonnull AttributeSet attrs) {String fName = attribute if (fname == null) {fname = attribute android:name} int Id = parse Android: ID attribute String tag = parse Android :tag attribute 2. Reuse the created Fragment based on the ID or tag Fragment = ID! = View.NO_ID ? findFragmentById(id) : null; if (fragment == null && tag ! = null) { fragment = findFragmentByTag(tag); } if (fragment == null && containerId ! = View.NO_ID) { fragment = findFragmentById(containerId); } 3, create a Fragment if (Fragment == null) {3.1 Creating a Fragment instance Fragment = getFragmentFactory().instantiate(context.getClassLoader(), fname); 3.2 mFromLayout set to True Fragment.mFromLayout = true; fragment.mFragmentId = id ! = 0? id : containerId; fragment.mContainerId = containerId; fragment.mTag = tag; fragment.mInLayout = true; fragment.mFragmentManager = this; fragment.mHost = mHost; fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState); 3.3 Adding a Fragment And immediately changing the status addFragment(true) } else if (fragment.mInLayout) { ... } else { ... } 4.1 Set id to Fragment root layout if (id! = 0) { fragment.mView.setId(id); } if (fragment.mview.getTag () == null) {fragment.mview.settag (tag); } return fragment.mview; } -> public void addFragment(Fragment Fragment, Boolean moveToStateNow) {... if (moveToStateNow) { moveToState(fragment); Void moveToState(Fragment f, int newState,...) {... if (f.mState <= newState ) { switch (f.mState) { case Fragment.INITIALIZING: if (nextState> Fragment.INITIALIZING) { ... } // fall through case Fragment.CREATED: if (f.mFromLayout && ! F. PerformedCreateView) {// If from the layout and the onCreateView final call is not executed:  mView = onCreateView(inflater, container, savedInstanceState); f.onViewCreated(f.mView, f.mSavedFragmentState); Finally execute viewGroup.addView(view, params) in LayoutInflater; } if (! F.layout) {mView = onCreateView(inflater, container, savedInstanceState); f.onViewCreated(f.mView, f.mSavedFragmentState); if (container ! = null) { container.addView(f.mView); }}... // fall through case Fragment.ACTIVITY_CREATED: ... // fall through case Fragment.STARTED: ... } } else { ... }}Copy the code

The above code has been very simplified, the code is long but the flow is very clear:

  • 1. The FragmentManager reuses fragments based on the ID attribute or tag attribute in the layout, or creates a Fragment instance by reflection if none exists.
  • 2. Set mFromLayout to True and perform the state transition immediately. The CREATE branch in moveToState() is judged by mFromLayout: if it is from a layout and onCreateView has not been executed, the View instance is created by calling Fragment#onCreateView.
  • 3. Finally, back in the LayoutInflater, execute ViewGroup#addView(mView) to add the Fragment root layout to the parent layout (so we don’t have to call addView() on views created in the Fragment).

Before I wrote an article has been discussed in detail in the layout of the whole process of parsing: Android | show you explore LayoutInflater layout analysis principle, on the part in section 4.2, remember to look at.

5.3 Fragment Dynamic loading source code analysis

The source code for a Fragment transaction was discussed in Section 4.4 (p. 53), and we know that fragments added/removed through a transaction will eventually go to moveToState(…). To perform state transitions. The mView is also added directly to the containerId container after the View instance is created.

5.4 What is the difference between static loading and dynamic loading?

The main difference between static and dynamic loading is the message cycle during which the load operation is performed: Static load and layout resolution are in the same Handler message cycle, while dynamic load and transaction commit are not necessarily in the same Handler message cycle (depending on whether commit() or commitNow() is called).

5.5 Advantages and disadvantages of static and dynamic loading?

This question seems reasonable, but actually can not stand scrutiny, is a false proposition. It is commonly said that static loading is simple and direct, while dynamic loading is flexible and high. What the people who make this claim are missing is that a Fragment loaded statically from a layout file can be dynamically manipulated using transactions, and static loading is flexible.

A more reasonable question is: which scenarios are suitable for static loading and dynamic loading? Static loading is suitable for fragments that determine the location and timing of the display when the interface is initialized, and loading from a layout file makes it easy to preview. In contrast, dynamic loading applies to fragments whose display location and timing cannot be determined at initialization, depending on the judgment conditions in the code for dynamic judgment.

Presentation: Using transactions operating static loading fragments from layout file with (supportFragmentManager. BeginTransaction ()) {val fragmentA = supportFragmentManager.findFragmentById(R.id.FragmentA) if (null ! = fragmentA) { hide(fragmentA) commit() } }Copy the code

6. What exactly does setRetainInstance() do?

In fact, the setRetainInstance() API has been deprecated since Androidx.Fragment 1.3.0. However, given the importance of this API, let’s take a moment to review it.

6.1 an overview of the

  • Question 1: When should you use setRetainInstance(true)?

A: When the configuration changes (such as screen rotation), the entire Activity needs to be destroyed and rebuilt, along with the Fragment in the Activity. Fragment objects with setRetainInstance(True) set will not be destroyed during Activity destruction and reconstruction.

  • Question 2: How does setRetainInstance(True) affect the Fragment lifecycle?

A: Instead of calling onDestroy(), the Fragment calls onDestroyView() + onDetach(); When an Activity rebuilds, the Fragment does not call back onCreate(), but onCreateView() directly.

  • Question 3: Why was setRetainInstance() discarded?

A: With the introduction of the ViewModel, the setRetainInstance() API began to become a bit of a dead end. The ViewModel already provides the ability to hold data in scenarios such as Activity reconstruction. Although setRetainInstance() has the same functionality, it requires fragments to store data indirectly, which is inconvenient to use and has too much granularity.

6.2 setRetainInstance() core source code analysis

Fragment.java

@Deprecated
public void setRetainInstance(boolean retain) {
    mRetainInstance = retain;
    if (mFragmentManager != null) {
        if (retain) {
            mFragmentManager.addRetainedFragment(this);
        } else {
            mFragmentManager.removeRetainedFragment(this);
        }
    } else {
        mRetainInstanceChangedWhileDetached = true;
    }
}
Copy the code

FragmentManager.java

void addRetainedFragment(@NonNull Fragment f) {
    mNonConfig.addRetainedFragment(f);
}
Copy the code

FragmentManagerViewModel.java

void addRetainedFragment(@NonNull Fragment fragment) { if (mIsStateSaved) { if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) { Log.v(TAG, "Ignoring addRetainedFragment as the state is already saved"); } return; } if (mRetainedFragments.containsKey(fragment.mWho)) { return; } mRetainedFragments.put(fragment.mWho, fragment); if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) { Log.v(TAG, "Updating retained Fragments: Added " + fragment); }}Copy the code

This code isn’t complicated, and when we call Fragment#setRetainInstance(true), we end up adding the Fragment to a ViewModel. The ViewModel has the ability to recover data in the Activity rebuild. Now the question is converted to the ViewModel why can recover data?

In simple terms, the Activity is destroyed, you will call Activity# retainNonConfigurationInstances () save ActivityClientRecord, And hosted to ActivityManagerService. This process is equivalent to saving the Fragment for a longer lifetime. As for the specific analysis of ViewModel, I will write a special article later, looking forward to it?


7. To summarize

We talked earlier about the origins of some of the historical problems with Fragments and some of their core features, including lifecycle, transactions, loading methods, and the outdated setRetainInstance(True). There are many other topics about fragments, and today we’ve only covered the core of them. I’ll be Posting more articles about them in the future.


The resources

  • Fragment past, Present, and Future — Google Developers
  • Fragment past, Present, and Future (Youtube Video version) — Android Dev Summit ’19
  • Fragment Guide – Official documentation
  • Your Activity has been rebuilt, so why should you live with your Fragment? – Wan Android
  • Today, take a look at two unusual fragent-related apis — Wan Android
  • How are fragments stored and restored? – Wan Android
  • Fragment Life Cycle by Kohachi Koki
  • Fragment unknown details — there was a luo

Creation is not easy, your “three lian” is chouchou’s biggest motivation, we will see you next time!