The life cycle of a dead Fragment

Source: Internet
Author: User

The life cycle of a dead Fragment

This article original, reproduced please indicate the source.
Welcome to my brief book, follow my topic Android Class I will long-term adherence to the book on the high-quality Android related blog post.

For the example in this article, GitHub address:

GitHub Project Links

Once on the subway in Beijing's congested line Line 13, a programmer with a double-shoulder bag and a plaid shirt with a cap and foot canvas shoes said:
"I think Fragment really is too hard to use." Which led to a flurry of heated discussion.

Affirmative view:

Fragment really good. To know that because the Activity starts, involves the Android system to the Activitymanager the dispatch, will relate many resources and carries on many complex computation, on some high-end handset, this scheduling time may even exceed the MS. Anti-Fragment, starting as smooth as the entrance of chocolate, light weight does not consume mobile resources. can also be made into a module to facilitate the Activity reuse. And if it involves the adaptation of the tablet, Fragment is essential.

Opposing views:

Fragment difficult to use, belong to the pit more difficult to fill. Fragment is essentially a life-cycle View with a wide life cycle and exceptionally difficult to manage, with multiple Fragment nesting pits (I've also met ... , even square and FaceBook have abandoned Fragment, not to mention us!

Well, don't argue, use or not, encounter problems how to solve, I believe everyone has an answer in their hearts. In combination with my own development problems, let's summarize the life cycle management of Fragment, along with some tips and advice.

Hide & Show

Combine a project first to visually see how I manage Fragment at the moment.

Because our project architecture is an Activity multi-Fragment, and all the Fragment are loaded into a viewpager inside, the process of starting a new Fragment is also the process of Viewpager sliding page, the future will consider this way of management Summarize the written, and organize to everyone. In short you see the interface, are Fragment rendered, and click on the button what, will also jump to the next Fragment, which involves the Fragment nested.

I also wrote a demo to simulate the construction of this page.

I want to say a few more words here.

The way to manage pages by clicking on the tabs below is currently very mainstream, and this layout is actually borrowed from IOS. (Anyway now the two systems are learning each other) in the previous Google's support 25 package also finally launched the official Bottomnavigationview, but my Android Studio installation support 25 always failed, so in the project I choose A good open source library to do the bottom navigation below.

Bottomnavigationview itself has a set of Material design specifications as follows:

Material Design Navigation Bottom

Interested to read, later on the product, design tear is very helpful. One of the interesting things about Bottomnavigationview is that it is not recommended to design it as a transverse sliding form, that is, to load Fragment with Viewpager. Why is it interesting to say that? In fact, many mainstream apps on the market, their bottomnavigationview really can not be horizontal sliding, and each of us in use, the month live 800 million of the national software, it is just the main page to make a horizontal sliding.

Here I would like to say my personal opinion, the first specification may not need to strictly abide by, what kind of function to achieve what effect, to combine their own project architecture and products to do a reasonable demand. Take 360 mobile phone assistant The app, for example, has a very "heavyweight" module at the bottom of each tab, and there are many responsible View levels and nested sliding viewpager inside each tab, so just imagine how this page would look like that and not lag Strange ~, first of all, I think its interface level and interaction are not complex, logic is also in the page, so the horizontal sliding can improve the user experience.

Well, before saying a lot of irrelevant words, hurry to see how the demo through hide and show how to manage Fragment.
Mainactivity

    PrivateSearchfragment searchfragment;PrivateMusicfragment musicfragment;PrivateCarfragment carfragment;PrivateSettingfragment settingfragment;PrivateBasefragment currentfragment;@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main); Butterknife.bind ( This);        Setsupportactionbar (toolbar);        Initview ();        InitData ();    Initlistener (); }Private void InitData() {if(Searchfragment = =NULL) {searchfragment = Searchfragment.newinstance (getString (r.string.tab_1)); }if(!searchfragment.isadded ()) {//Commit a transactionGetsupportfragmentmanager (). BeginTransaction (). Add (R.id.fl_content, searchfragment). commit ();//Record current fragmentCurrentfragment = searchfragment; }    }Private void Initlistener() {Bottomnavigation.setontabselectedlistener (NewAhbottomnavigation.ontabselectedlistener () {@Override             Public Boolean ontabselected(intPositionBooleanwasselected) {LOG.D (TAG,"Ontabselected:position:"+ Position +", wasselected:"+ wasselected);if(Position = =0) {//NavigationClicksearchlayout (); }if(Position = =1) {//MusicClickmusiclayout (); }if(Position = =2) {//OBDClickcarlayout (); }if(Position = =3) {clicksettinglayout (); }return true;    }        }); }Private void Clicksearchlayout() {if(Searchfragment = =NULL) {searchfragment = Searchfragment.newinstance (getString (r.string.tab_1));    } addorshowfragment (Getsupportfragmentmanager (). BeginTransaction (), searchfragment); }Private void Clickmusiclayout() {if(Musicfragment = =NULL) {musicfragment = Musicfragment.newinstance (getString (r.string.tab_2));    } addorshowfragment (Getsupportfragmentmanager (). BeginTransaction (), musicfragment); }Private void Clickcarlayout() {if(Carfragment = =NULL) {carfragment = Carfragment.newinstance (getString (r.string.tab_3));    } addorshowfragment (Getsupportfragmentmanager (). BeginTransaction (), carfragment); }Private void Clicksettinglayout() {if(Settingfragment = =NULL) {settingfragment = Settingfragment.newinstance (getString (r.string.tab_4));    } addorshowfragment (Getsupportfragmentmanager (). BeginTransaction (), settingfragment); }/** * Add or Show fragment * * @param transaction * @param Fragment * *    Private void addorshowfragment(fragmenttransaction transaction, Fragment Fragment) {if(currentfragment = = fragment)return;if(!fragment.isadded ()) {//If the current fragment is not added, it is added to the Fragment managerTransaction.hide (currentfragment). Add (r.id.fl_content, Fragment). commit (); }Else{transaction.hide (currentfragment). Show (fragment). commit ();    } currentfragment = (basefragment) fragment; }

The code was easy to understand, and I managed to switch between the four tabs at the bottom with add & Show/hide, and printed all the life-cycle methods of the four Fragment, including onHiddenChanged andsetUserVisibleHint

When entering a page for the first time:

Can see, when I click on the bottom four tab, the interface first load, will walk Fragment creation cycle Onattach–onresume, perhaps you will ask, above I perform mutual switch operation, from the first page to switch to the second, why the first Fragment The page is not visible, onPause and onStop are not called?

This is the first mistake you can get into when you know the Activity life cycle and just contact Fragment's life cycle, in fact the life cycle of Fragment, except for the first time it is created or destroyed, is driven by Activity. For example, when I click the Home button to go back to the desktop:

You can see that I have loaded several Fragment uniform called OnPause and onStop, so unison is because these Fragment attach Activity callback OnPause and OnStop. I'm sure someone will say, "No, I'm going to switch Fragment with replace, I'm going to pack the tickets, Fragment like the Activity, complete the life cycle."

You are right, because replace this switching mode is always above I summed up the sentence "first created or destroyed", and in bottomnavigation such a usage scenario, no one will use this way of replace, because each switch to re-create Fragment, The user has seen the next traffic estimate will hit 12315.

(If Fragment represents ex-boyfriend/girlfriend, it is said that men are saved with ADD, women use replace replace HHH ...) )

When the bottom of the four Fragment have been loaded complete? Let's look at the log together:

When the bottom four Fragment all created into the stack, show and hide to manage the Fragment, at this time only the onHiddenChanged method callback, it is obvious that you can at the hide = false time, do some resource recycling operations, hide = true when, do some refreshing operation.

In the method we printed just now, it seems that one has never appeared, yes setUserVisibleHint , if you have done fragment+viewpager lazy loading (we will talk about this later), I believe you are more familiar with it, by name can guess, this method is our initiative to set to Fragment, let's try it out:

Retrofit addOrShowFragment

    /** * Add or Show fragment * * @param transaction * @param Fragment * *    Private void addorshowfragment(fragmenttransaction transaction, Fragment Fragment) {if(currentfragment = = fragment)return;if(!fragment.isadded ()) {//If the current fragment is not added, it is added to the Fragment managerTransaction.hide (currentfragment). Add (r.id.fl_content, Fragment). commit (); }Else{transaction.hide (currentfragment). Show (fragment). commit (); } currentfragment.setuservisiblehint (false);        Currentfragment = (basefragment) fragment; Currentfragment.setuservisiblehint (true); }

When switching, we set the previous fragment to setUserVisibleHint false, to show the fragment setUserVisibleHint set to True, print log to see:

We can see that at present we have achieved the same effect as onhiddenchanged with Setuservisiblehint.

The article writes now, we come to make a summary, above this way is the mainstream through bottomnavigation management Fragment Way, what is the advantage of this way? There is no doubt that the resources will be saved, the interface is not to create it (this point viewpager do not), only created once, in the future just update the interface data can be.

Viewpaager & Fragment

Viewpager and Fragment with the use of trust most people are very familiar with, since the quick to summarize what I think need to comb clear a few knowledge points, first look at the page I build:

I am in this module of navigation, has built a tablayout+viewpager+fragment page structure, when launches the app, enters the homepage, each Fragment life cycle method is how?

As you can see, when I enter the app, all Tab's parent container searchfragment created, called Onattach–> Onresume This is of course what we expected, we viewpager the first to load and show the Sciencefra Gment,sciencefragment created without a problem, but why is the second tab gamefragment loaded?

Yes, that's Viewpager's preload mechanism.

Viewpager to optimize the experience of kindness, the default to load the next two pages, to ensure the smoothness of the sliding as far as possible, but if we are a news app, each tab involves a complex page and a large number of network requests, this preload mechanism may be the trouble. So we're looking for some way to try and get rid of the viewpager preload.

Viewpager itself provides a way to mViewPager.setOffscreenPageLimit() interpret the official documentation for this method:

It means to set the number of cached pages on the left and right side of the Viewpager, the default is 1, then we set it to 0, is it possible to cancel the pre-loading it? And look at this piece of honey Juice source code:

In short, the source code means that you set the value of less than 1 is the default of 1, anyway, this road does not work now.

Of course, there is a way, you directly modify the source code after a V4 package, but it is not recommended to do so, the future will have some compatibility issues.

Well, you should know right away. Viewpager lazy loading, is to use the Setuservisiblehint method we mentioned above, when I swipe around, to see the printed log:

There are two problems that can be analyzed from log, first setuservisiblehint This method may be called before Onattach, followed by setting the page in the swipe beyond the number of cache pages is indeed destroyed.

Looking back to the previous article, obviously said Setuservisiblehint this method needs to be active call, that in Viewpager, Fragment Setuservisiblehint method is who when call?

My Viewpager Adapter is here:

 Public  class maintabadapter extends fragmentstatepageradapter {    PrivateList<fragment> mlist;PrivateString mtabtitle[] =Newstring[]{"Technology","Game","Equipment","Entrepreneurship","Idea"}; Public Maintabadapter(Fragmentmanager FM, list<fragment> List) {Super(FM);    mlist = list; }@Override     PublicFragmentGetItem(intPosition) {returnMlist.get (position); }@Override     Public int GetCount() {returnMlist.size (); }@Override     PublicCharsequenceGetpagetitle(intPosition) {returnMtabtitle[position]; }}

It seems that fragmentstatepageradapter can do this thing, click to see:

Fragmentstatepageradapter This class is actually a package class for pageradapter, less than 200 lines of code, indeed found the setuservisiblehint.

There are two places called Setuservisiblehint, the first position:

Second position:

The logic of the source processing here is this:

In the Instantiateitem method, take the corresponding positon Fragment in my data collection, set the Setuservisiblehint to False, and then add it to the Fragmenttransaction , which explains exactly why Setuservisiblehint's first call was before Onattach.

The next Setuservisiblehint setting is in setPrimaryItem , setPrimaryItem This method can get the Fragment that the current Viewpager is showing, and the setuservisiblehint of the previous Fragment is set to Fals E, set the Setuservisiblehint that will be displayed to true.

By reading the source code, we understand the principle, so directly to everyone on the basefragment implementation of lazy loading codes:

 Public  class basefragment extends Fragment {    protected Booleanisviewcreated =false;@Nullable    @Override     PublicViewOncreateview(Layoutinflater inflater, @Nullable viewgroup container, @Nullable Bundle savedinstancestate) {return Super. Oncreateview (Inflater, container, savedinstancestate); }@Override     Public void Setuservisiblehint(BooleanIsvisibletouser) {Super. Setuservisiblehint (Isvisibletouser);if(Getuservisiblehint ())        {Lazyloaddata (); }    }/** * Lazy Loading method * /    protected void Lazyloaddata() {    }}

Lazy loading in a specific Fragment

 Public  class sciencefragment extends basefragment {    @Nullable    @Override     PublicViewOncreateview(Layoutinflater inflater, @Nullable viewgroup container, @Nullable Bundle savedinstancestate) {View view = Inflater.inflate (R.layout.fragment_science, container,false); LOG.E (TAG,"Oncreateview"); isviewcreated =true;returnView }@Override    protected void Lazyloaddata() {Super. Lazyloaddata ();if(isviewcreated) {LOG.E (TAG,"Lazyloaddata ..."); }    }}

Look at the log:

As you can see, lazy loading is done.

Here we do a phase summary, first of all we have to understand setuservisiblehint this is viewpager behavior, it is always ahead and Fragment life cycle call. We can use lazy to load this approach, mainly because the pre-loaded Fragment has been created all the way to call the onattach–> OnPause, which means that this Fragment is available at this time, lazy loading for reasons to take effect. I don't know if it's hard to understand, but running the example of this article will definitely make sense of the above paragraph.

So when Fragment is first created, lazy loading will not be called at the same time, so let's continue to optimize the optimization, we let Viewpager load the five Fragment layout together, and then lazy loading will be available all the way ~

  mViewPager.setOffscreenPageLimit(5);

Either I swipe or click the tab above to jump to any page, the lazyLoadData method will be called, we can load the layout first, and then when visible refresh data is OK.

About the management of Fragment, is mainly the above two ways, of course, specific to each person's own project, need to analyze the needs and product ideas to find a suitable way. When we know the principle, do the operation of the heart is much more, out of the problem can also be quickly positioned.

Above we Viewpager adapter use is Fragmentstatepageradapter, there is a fragmentpageradapter, because the length of this article is too long, the next will summarize their differences in the source angle, And some of the pits that have been trampled during use. (If there are some strange problems that cannot be solved, it is recommended to use Fragmentstatepageradapter first).

Written at the end:

We look back at the beginning of the argument, Fragment use it? For most developers, of course, I personally really like Fragment, the use of Fragment can embody the idea of Android components, which brings developers more convenience than trouble. Although its life cycle is complex, the stack is strangely difficult to manage, but when the right posture uses Fragment (do not nest Fragment use), go through a pit, Fragment naturally also have confidence.

Finally, a picture of Fragment life cycle ~

The life cycle of a dead Fragment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.