Solutions to fragment management and overlapping problems in Android _android

Source: Internet
Author: User
Tags commit

First, Fragment introduction

Fragment in 3.0 after the introduction of the project to use more and more Fragment, especially the main interface is the bottom tab click to switch the replacement content, of course, Fragment in the project exists a wide range of times, such as usually in the home page design, usually at the bottom of every Navigation corresponds to this corresponding Fragment, using Fragment to mitigate the responsibility of the corresponding activity, so that fragmen T acts as part of the activity's responsibility. And the use of Fragment, improve the code and layout of the encapsulation and reuse, this advantage is particularly obvious.

Fragment has its own lifecycle management, but it relies on the corresponding activity.

Well, the life cycle of the introduction is not the focus of this article, put a picture to deepen the impression.

Second, the fragment stack management and its life cycle

Addtoshow

Fragmenttransaction transaction = Manager.begintransaction ();
 String tag = To.getclass (). Getsimplename ();
 Transaction.add (From.getcontainerid (), to, tag).
   Addtobackstack (tag)-
   Hide (from)
   .
   Commit ();

If you use add() and hide() to control the jump, the corresponding lifecycle is this:

e/tag:onattach:fragment09
 e/tag:oncreate:fragment09
 e/tag:oncreateview:fragment09
 e/tag:onstart: Fragment09
 e/tag:onresume:fragment09
 e/____tag____: onclick:2131558527
 e/tag:onattach:fragment10
 e/tag:oncreate:fragment10
 E/tag:onhiddenchanged:fragment09 's not seen!
 e/tag:oncreateview:fragment10
 E/tag:onstart:fragment10
 e/tag:onresume:fragment10

If you return to the first Fragment from the second Fragment at this time:

E/tag:onhiddenchanged:fragment10 's not seen!
 e/tag:onhiddenchanged:fragment09 Visible!!
 e/tag:onpause:fragment10
 E/tag:onstop:fragment10
 e/tag:ondestroyview:fragment10
 e/tag:ondestroy:fragment10
 E/TAG: Ondetach:fragment10

can correspond to the above picture, when return is the direct destruction of the current Fragment, and then the first Fragment only from the invisible state to the visible state, and do not go to the relevant life cycle, so hide() the method does not trigger the onPause() life cycle callback method.

So if we lock the screen or switch to the task and then switch back:

e/tag:onpause:fragment09
 e/tag:onpause:fragment10
 e/tag:onstop:fragment09
 e/tag:onstop:fragment10< c4/>e/tag:onstart:fragment09
 e/tag:onstart:fragment10
 e/tag:onresume:fragment09
 e/tag:onresume: Invisible Fragment09
 e/tag:onresume:fragment10
 e/tag:onresume: Visible Fragment10

As you can see here, all the Fragment go back to the activity to recall the associated method, whether it is visible or not.

Replaceto

Fragmenttransaction transaction = Manager.begintransaction ();
 String tag = To.getclass (). Getsimplename ();
 Transaction.replace (From.getcontainerid (), to, Tag)
   . Addtobackstack (TAG)
   . commit ();

replace() method is to remove() remove all Fragment that were added to the container before add() adding the current one. So since remove() the method is invoked, so is the lifecycle:

e/tag:onattach:fragment09
 e/tag:oncreate:fragment09
 e/tag:oncreateview:fragment09
 e/tag:onstart: Fragment09
 e/tag:onresume:fragment09
 e/tag:onresume: Visible Fragment09
 e/____tag____: onclick:2131558527
 e/tag:onattach:fragment10
 E/tag:oncreate:fragment10
 e/tag:onpause:fragment09
 e/tag:onstop:fragment09
 E/tag:ondestroyview: Fragment09
 e/tag:oncreateview:fragment10
 e/tag:onstart:fragment10
 e/tag:onresume:fragment10
 E/tag:onresume: The Visible Fragment10

In contrast to the log above, when the remove() call is made, Fragment executes, and is onPause() onStop() onDestroyView() invoked once, but onDestroy() onDetach() is not invoked, which means that its view will be destroyed, and then come back again, You have to re-create:

E/tag:onpause:fragment10
 e/tag:onstop:fragment10
 e/tag:ondestroyview:fragment10
 E/tag:ondestroy: Fragment10
 e/tag:ondetach:fragment10
 e/tag:oncreateview:fragment09
 e/tag:onstart:fragment09
 E/ Tag:onresume: The Visible Fragment09

Again, lock the screen or switch back after the task:

E/tag:onstart:fragment10
 e/tag:onresume: Visible Fragment10
 e/tag:onpause:fragment10
 e/mainactivity: Onsaveinstancestate: Save the current TAG
 e/tag:onstop:fragment10
 e/tag:onstart:fragment10
 e/tag:onresume: Visible Fragment10

As you can see, when used replace() , these situations will only have top Fragment to respond to the corresponding lifecycle. In the above add() , two Fragment have gone through the related lifecycle.

So the question is: when to use replace() and when to add() use hide() it?! In fact, in contrast, the main problem is efficiency and related life cycle problems.

Efficiency issues:

If used replace() means each need to go onCreateView() again to repopulate the layout. If you onCreateView() also include initialization data in the method, it also means that the relevant one is executed again.

Data, page refresh issues:

If you use the replace() jump from Afragment to Bfragment, bfragment update the relevant data will affect the afragment of the relevant View display, there will be a problem, even if you use Eventbus what the notice, Afrag ment can indeed change, but when you cut back to afragment, it goes back and onCreateView() creates the relevant layout, unless you save it to the global, initialize it again, then the data you send will be lost.

Life cycle Matching problem:

The methods of the lifecycle are matched in pairs, and in the method mentioned above replace() , A is replaced with the following three life cycle callback methods:

e/tag:onpause:fragment09
 e/tag:onstop:fragment09
 e/tag:ondestroyview:fragment09

When it is rolled back, the corresponding three lifecycle callbacks are invoked:

e/tag:oncreateview:fragment09
 e/tag:onstart:fragment09
 e/tag:onresume: Visible Fragment09

But the use add() and hide() the time will be more awkward, you will find it onPause() and the onResume() method completely does not match. As long as add() , even if you call hide() , will not affect its lifecycle callback, there will be no onPause() such callbacks. That's what happens when we lock the screen or switch the task back, all add Fragment will perform the related lifecycle callback method:

e/tag:onpause:fragment09
 e/tag:onpause:fragment10
 e/tag:onstop:fragment09
 e/tag:onstop:fragment10
 e/tag:onstart:fragment09
 E/tag:onstart:fragment10
 e/tag:onresume:fragment09
 e/tag:onresume: Invisible Fragment09
 E/tag:onresume : Fragment10
 e/tag:onresume: Visible Fragment10

So, if you do statistics, here's a little bit of a problem. Of course, it is not entirely unknowable whether it is displayed or not.

A isHide() method, or a method, that can be used in Fragment onHiddenChanged(boolean hiden) to obtain whether the current is a hide state.

So summed up is the use add() , hide() the way, need to pay attention to the mismatch of the onResume() callback method and the timing of the data, should be visible (Ishidden () return False when) to request the relevant data.

replace() the use of words is to pay attention to frequent layout fill and the Fragment and Fragment between the data transfer situation.

State Save

Fragment overlapping anomalies

Must have met the problem of fragment overlapping display!?

This is primarily a problem that occurs when an activity helps us in a related state of recovery. Background processes are not kept open in the settings, facilitating the corresponding situation:

And then on the second page, back to the homepage, again, let's take a look at an exception log:

e/tag:onattach:fragment09
 e/tag:oncreate:fragment09
 e/tag:onattach:fragment10
 e/tag:oncreate: Fragment10
 e/tag:oncreateview:fragment09
 e/tag:oncreateview:fragment10
 e/tag:onattach:fragment09
 e/tag:oncreate:fragment09
 e/tag:oncreateview:fragment09
 e/tag:onstart:fragment09
 e/tag:onstart:fragment10
 e/tag:onstart: Fragment09
 e/tag:onresume: Invisible Fragment09
 e/tag:onresume: Visible Fragment10
 e/tag:onresume: Visible Fragment09

Did you find the problem? Our Fragment9 was created two times. One is the same, invisible, and the other is visible, and still on top. So this creates a Fragment overlap.

There is also a situation where a breakpoint found that a Fragment was initialized successfully, and the layout is there, but the view inside is empty, and I have encountered it.

Why is this problem occurring? Because in this exceptional case, the Android temporary data retention mechanism is triggered, and Fragment is the focus of its temporary preservation. So the previous two Fragment related states have been saved! But that's what onCreate() I wrote in the activity:

Fragmentsutil.loadroot (R.id.fragment_container, Fragment9.newinstance ());

So, whether there is a saved state I go to create a load again Fragment9, so this leads to the creation of the Fragment9 two times (once the system is restored, the relevant state is also normal, once we are created in the onCreate() ). So to avoid this problem, we should try to find a way to savedinstancestate this thing. Now that it has saved the relevant Fragment, we don't have to create it again!

@Override
protected void onCreate (Bundle savedinstancestate) {
 super.oncreate (savedinstancestate);
 Setcontentview (r.layout.activity_main);
 Butterknife.bind (this);
 Manager = Getsupportfragmentmanager ();
 if (savedinstancestate = null) {
  LOG.E (TAG, "onsaveinstancestate: Restore related state!!) ");
  Fragmentsutil.loadroot (R.id.fragment_container, Fragment9.newinstance ());
 }

So, Savedinstancestate still can't be ignored. But when you think it's over, it's too underrated Fragment's pit, if your support-library is below 24, then even if you judge Savedinstancestate again to create but there is also the possibility of overlapping situation!

Here's the Fragmentstate class, which is used to hold the Fragment associated state.

Did you find anything? In the previous fragmentstate did not save the Mhidden state!

The related issue submissions were also searched, but the associated bug fixes were not seen in the Android revision-history. So when exactly when the formal addition of the Mhidden field is no textual research out.

Chat so much, finally said the solution Bai, in fact, the principle is very simple, since it does not automatically save, then we will save the state of the manual Mhidden State Save, in the initialization of the time according to the saved Mhidden State manual display or hidden.

@Override public
void Onsaveinstancestate (Bundle outstate) {
 //Manually Save
 Outstate.putboolean (Arg_is_hidden, Ishidden ());
 Super.onsaveinstancestate (outstate);
}
 OnCreate when calling the public
void Initfragments (Bundle savedinstancestate, basefragment fragment) {
 if ( Savedinstancestate = = null) {return
  ;
 }
 Boolean Issupporthidden = Savedinstancestate.getboolean (Arg_is_hidden);

 Fragmenttransaction ft = manager.begintransaction ();
 if (Issupporthidden) {
  ft.hide (fragment);
 } else {
  ft.show (fragment);
 }
 Ft.commit ();
}

Finally, a simple tool class and basefragment are encapsulated to handle Fragment related transactions.

Summarize

This is the full content of this article, I hope the content of this article for your Android developers can help, if you have questions you can message exchange.

Related Article

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.