Android FAQ-Why use Fragment.setarguments (bundle bundle) to pass parameters (go)

Source: Internet
Author: User

Fragment is available at Android3.0 and provides support for fragment features in the Compatibility Pack. The launch of fragment allows us to write and manage the user interface more quickly and easily. But when we instantiate a custom fragment, why is it that the fragment.setarguments (bundle bundle) is officially recommended as a way to pass parameters, rather than simply passing them through a constructor method? In order to understand this problem, we can do a test to test the difference between the two methods first, we test the case of passing parameters by constructing method

 Public classFramenttestactivityextendsactionbaractivity {@Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate);        Setcontentview (R.layout.activity_main); if(Savedinstancestate = =NULL) {Getsupportfragmentmanager (). BeginTransaction (). Add (R.id.container,NewTestfragment ("param") . commit (); }            }     Public Static classTestfragmentextendsFragment {PrivateString MArg = "Non-param";  Publictestfragment () {LOG.I ("INFO", "Testfragment Non-parameter constructor"); }                 Publictestfragment (String Arg) {MArg=Arg; LOG.I ("INFO", "testfragment construct with parameter"); } @Override PublicView Oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { View Rootview=inflater.inflate (R.layout.fragment_main, container,false); TextView TV=(TextView) Rootview.findviewbyid (r.id.tv);            Tv.settext (MARG); returnRootview; }    }}

Can see the data we passed over the correct display, and now to consider a problem, if the device configuration parameters change, here to the screen to explain the problem, display the following

What's going on? What happened to the parameters we passed? Why is the default value displayed? Don't worry about it, let's take a look at how the Fragment.setarguments (bundle bundle) works.

 Public classFramenttest2activityextendsactionbaractivity {@Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate);              Setcontentview (r.layout. Activity_main); if(Savedinstancestate = =NULL) {Getsupportfragmentmanager (). BeginTransaction (). Add (r.id. Conta Iner, Testfragment.newinstance ("Param") . commit (); }       }         Public Static classTestfragmentextendsFragment {Private Static FinalString arg = "ARG";  Publictestfragment () {Log. I ("INFO", "Testfragment Non-parameter constructor" ); }               Public StaticFragment newinstance (String Arg) {testfragment Fragment=Newtestfragment (); Bundle Bundle=NewBundle ();                    Bundle.putstring (ARG, ARG);                     Fragment.setarguments (bundle); returnfragment; } @Override PublicView Oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) {View Rootview=inflater.inflate (r.layout fragment_main, container,false); TextView TV=(TextView) Rootview.findviewbyid (r.id. TV);                     Tv.settext (Getarguments (). getString (ARG)); returnRootview; }       }}

Let's take a look at the running situation after the screen switch.

See, we passed the parameters in the case of the screen switch in the situation intact saved down, the correct display to the user so what is the matter, we know the device to switch, the current display to the user's activity by default will be re-created and presented to the user, The fragment that is attached to the activity will handle it, and we can view the OnCreate (Bundle saveinstance) method of the activity by the source code.
     protected voidonCreate (Bundle savedinstancestate) {if(debug_lifecycle) SLOG.V (TAG, "onCreate" + This+ ": " +savedinstancestate); if(Mlastnonconfigurationinstances! =NULL) {mallloadermanagers=mlastnonconfigurationinstances. Loaders; }        if(mactivityinfo. Parentactivityname! =NULL) {            if(Mactionbar = =NULL) {Menabledefaultactionbarup=true ; } Else{mactionbar. setdefaultdisplayhomeasupenabled (true); }        }        if(Savedinstancestate! =NULL) {parcelable P=savedinstancestate.getparcelable (Fragments_tag); Mfragments. Restoreallstate (p, mlastnonconfigurationinstances!=NULL? Mlastnonconfigurationinstances. Fragments:NULL);        } mfragments. Dispatchcreate (); Getapplication (). dispatchactivitycreated ( This, savedinstancestate); Mcalled=true ; }

Since our fragment is managed by Fragmentmanager, we can follow the Fragmentmanager.restoreallstate () method and find the following block of code by fragmnet the current activity

   for(inti=0; i<fms.mactive.length; i++) {Fragmentstate fs=Fms.mactive[i]; if(FS! =NULL) {Fragment F=fs.instantiate (mactivity, mparent); if(DEBUG) LOG.V (TAG, "restoreallstate:active #" + i + ":" +f);               Mactive.add (f); //Now , the fragment is instantiated (or came from being//retained above), clear minstance in case we end up re-restoring//From this fragmentstate again.Fs.minstance =NULL; } Else{Mactive.add (NULL); if(Mavailindices = =NULL) {mavailindices=NewArraylist<integer>(); }               if(DEBUG) LOG.V (TAG, "Restoreallstate:avail #" +i);           Mavailindices.add (i); }}

Next we can look at the implementation of the Fragmentstate.instantitate () method

 PublicFragment Instantiate (activity activity, Fragment parent) {if(Minstance! =NULL) {            returnminstance; }               if(Marguments! =NULL) {marguments. Setclassloader (Activity.getclassloader ()); } minstance=fragment.instantiate (activity, Mclassname, marguments); if(Msavedfragmentstate! =NULL) {msavedfragmentstate. Setclassloader (Activity.getclassloader ()); Minstance. Msavedfragmentstate=msavedfragmentstate;        } minstance. Setindex (Mindex, parent); Minstance. Mfromlayout=mfromlayout; Minstance. mrestored=true; Minstance. Mfragmentid=Mfragmentid; Minstance. Mcontainerid=Mcontainerid; Minstance. Mtag=Mtag; Minstance. Mretaininstance=mretaininstance; Minstance. mdetached=mdetached; Minstance. Mfragmentmanager=activity.mfragments; if(Fragmentmanagerimpl.debug) log.v (Fragmentmanagerimpl.tag,"Instantiated fragment" +minstance); returnminstance; }

You can see the final transfer to the Fragment.instantitate () method

      Public StaticFragment Instantiate (context context, String fname, Bundle args) {Try{Class<?> Clazz =sclassmap. Get (fname); if(Clazz = =NULL) {                //Class not found in the cache, see if it's real, and try to add itClazz =Context.getclassloader (). LoadClass (fname);            Sclassmap. Put (fname, clazz); } Fragment F=(Fragment) clazz.newinstance (); if(Args! =NULL) {Args.setclassloader (F.getclass (). getClassLoader ()); F. Marguments=args; }            returnF; } Catch(ClassNotFoundException e) {Throw NewInstantiationexception ("Unable to instantiate fragment" +fname+ ": Make sure class name exists, was public, and have a" + "empty constructor that's public", E); } Catch(java.lang.InstantiationException e) {Throw NewInstantiationexception ("Unable to instantiate fragment" +fname+ ": Make sure class name exists, was public, and have a" + "empty constructor that's public", E); } Catch(illegalaccessexception e) {Throw NewInstantiationexception ("Unable to instantiate fragment" +fname+ ": Make sure class name exists, was public, and have a" + "empty constructor that's public", E); }    }
As you can see, a new fragment is eventually instantiated through a reflection-free construct, and the margments is initialized to the original value, and the original fragment instance data is lost and initialized again.


From the above analysis, we can know that when the activity is re-created, it will rebuild the fragment it manages, and the original fragment field values will all be lost, but through fragment.setarguments (bundle bundle) The bundle of method settings is preserved. So try to use the Fragment.setarguments (Bundle bundle) method to pass the parameters

Android FAQ-Why use Fragment.setarguments (bundle bundle) to pass parameters (go)

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.