The use of Android Fragment, some of the things you should be aware of

Source: Internet
Author: User

Fragment, commonly known as fragments, has been introduced and used extensively since Android 3.0. However, it is such a familiar thing, in the development we will still meet a variety of problems, endless. So, it's time to sum up a wave.

Fragment Introduction

As part of the activity interface, the presence of Fragment must be dependent on activity and, like activity, has its own life cycle, while handling the user's interaction. The same Activity can have one or more Fragment as the interface content, and can dynamically add, delete Fragment, flexible control UI content, can also be used to solve some screen adaptation problems.

In addition, the support V4 package also provides the Fragment, compatible with Android 3.0 before the system (of course, now 3.0 before the system is rarely seen in the market, can not be considered), using the Compatibility pack need to pay attention to two points:

    • Activity must inherit from Fragmentactivity;

    • Use the Getsupportfragmentmanager () method to get the Fragmentmanager object;

Life cycle

As part of the host activity, most of the life cycle functions owned by activity are also present in Fragment and are synchronized with the activity. At the same time, as a special case, Fragment also has some of its own life cycle functions, such as Onattach (), Oncreateview () and so on.

As for the synchronization relationship between Activity and the life cycle function of Fragment, the Xxv/android-lifecycle project from GitHub is perfectly presented with a picture:

About Fragment each life cycle function meaning, here does not describe each, may refer to the official website introduction: Fragment Lifecycle.

Create an instance

Like normal classes, Fragment has its own constructors, so we can create Fragment instances in the Activity as follows:

new MainFragment();

If you need to pass parameters to initialize when you create an Fragment instance, you can create a constructor with parameters, initialize the Fragment member variable, and so on. This does not seem to be a problem, but there are still problems in some special situations.

We know that activity in some special situations will occur destroy and re-create the situation, such as screen rotation, memory is tight, corresponding to the presence of activity in the Fragment will also occur similar situation. Once the Create is recreated, the default parameterless constructor is called by Fragment, resulting in the inability to perform initialization work with the parameter constructor.

Fortunately Fragment provided the appropriate API to help us solve this problem. Using bundles to pass data, the reference code is as follows:

public  static  onefragment newinstance  (    int  args) {onefragment onefragment = new  onefragment ();    Bundle bundle = new  bundle ();    Bundle.putint ( "Someargs" , args);    Onefragment.setarguments (bundle); return  onefragment;}  @Override  public  void  oncreate  (@Nullable Bundle savedinstancestate)    {super . OnCreate (savedinstancestate);    Bundle bundle = Getarguments (); int  args = bundle.getint ();}  
Embedding method

Activity embedding Fragment is divided into two kinds: layout static embedding and code dynamic embedding. The former uses tags to embed the specified Fragment in the layout of the Activity <fragment> , such as:

<?xml version= "1.0" encoding= "Utf-8"?><linearlayout xmlns:android="Http://schemas.android.com/apk/res/android"  Android:layout_width="Match_parent"android:layout_height="Match_parent"  Android:orientation="vertical">                <fragmentandroid:layout_width="Match_parent"android:layout_height= "Match_parent" class="com.yifeng.samples.OneFragment"/>                        </linearlayout>

The latter replaces the corresponding container layout in the activity's layout with the Replace () method provided by the manager class Fragmentmanager and Transaction class fragmenttransaction in the activity's Java code, such as:

FragmentManager fm = getFragmentManager();FragmentTransaction ft = fm.beginTransaction();ft.replace(R.id.fl_content, OneFragment.newInstance());ft.commit();

The two embedding methods correspond to a slightly different Fragment life cycle, as can be seen from the life cycle diagram. Code dynamic embedding method is more common than static embedding mode, after all, the latter can flexibly control multiple Fragment and dynamically change the contents of Activity.

Getchildfragmentmanager ()

As above, when the activity is embedded in the Fragment, it needs to use Fragmentmanager, which can be obtained through the Getfragmentmanager () method provided by the activity to manage all the first-level Fr embedded in the activity. Agment.

Sometimes, however, we will continue to nest two or even three levels of Fragment in Fragment, that is, Activity nesting multi-level Fragment. At this time in the Fragment management sub-Fragment, also need to use to Fragmentmanager. But be sure to get the Fragmentmanager object using the Getchildfragmentmanager () Method!

The differences between the Fragmentmanager objects obtained by these two methods can also be seen from the official documentation annotations:

Activity:getfragmentmanager ()

Return the Fragmentmanager for interacting with fragments associated and this activity.

Fragment:getchildfragmentmanager ()

Return a private Fragmentmanager for placing and managing fragments inside of this Fragment.

Fragmenttransaction

Fragment dynamic additions, deletions and other operations need to be done with the help of the Fragmenttransaction class, such as the replace () operation mentioned above. Fragmenttransaction provides a lot of methods for developers to operate the activity inside the Fragment, specifically, can refer to the official website: fragmenttransaction public Methods, Here are a few common key approaches:

    • Add () Series: Adds Fragment to the Activity interface;

    • Remove (): Removes the specified Fragment in the Activity;

    • Replace () Series: Completes the Fragment modification by calling remove () and add () internally;

    • Hide () and show (): Hides and shows the Fragment in Activity;

    • Addtobackstack (): Adds the current transaction to the fallback stack, that is, when the return key is pressed, the interface reverts to the current state of the thing;

    • Commit (): Commit the transaction, all changes to Fragment through the above methods must be done by calling the commit () method to complete the commit;

Note: When dynamic toggle displays multiple Fragment in Activity, it can be implemented by replace () or by the Hide () and show () methods. In fact, we prefer to use the latter because the replace () method does not preserve the state of Fragment, which means that user actions such as EditText content input disappear at remove (). Of course, if you do not want to retain user action, you can choose the former, depending on the situation.

Backstack (fallback stack)

The current transaction is saved through Addtobackstack (), and when the user presses the return key, if the previous transaction is saved in the fallback stack, the transaction fallback is performed instead of the current Activity being erased.

For example, there is a new user registration function in the APP, including setting the user name, password, mobile phone number and so on, the designer in the UI design of each process individually designed as an interface, guide the user Step-by-step operation. As a developer, it is cumbersome to operate a single Activity for each process of perfecting the information, and it is not easy to handle the logic in the application, but if you use Fragment and combine the fallback stack, it is very appropriate.

The process of each set is written as a Fragment, the different Fragment are displayed by state control, and the fallback stack is used to implement the function of returning the previous operation. For example, when entering secondstepfragment from Firststepfragment, you can do this in Loginactivity.java:

FragmentManager fm = getSupportFragmentManager();FragmentTransaction ft = fm.beginTransaction();ft.hide(firstStepFragment);if (secondStepFragment==null){    ft.add(R.id.fl_content, secondStepFragment);}else {    ft.show(secondStepFragment);}ft.addToBackStack(null);ft.commit();

Note: The Hide () method is used here, not the Replace () method, because we certainly want the user to return to the previous action, and the previously set content will not disappear.

Communication mode

In general, there are three scenarios in which Fragment communicates with activity: The Fragment,fragment Operation host activity,fragment operations that are embedded in the activity operation are the same as other Fragment in the activity.

Because Activity holds all embedded Fragment object instances (Fragment objects that were saved when the instance was created, or Findfragmentbyid () and Findfragmentbytag () provided through the Fragmentmanager class) Method can also get to the Fragment object), so you can directly manipulate the fragment;fragment through getActivity() the method to get to the host activity object (cast type), so that the host activity can be manipulated; it's natural to get to the host The Fragment of the Activity object can manipulate other Fragment objects.

Although the above operations have been able to solve the Activity and Fragment communication problems, but will cause code logic disorder results, extremely incompatible with this programming idea: cohesion Poly, low coupling. Fragment do their own thing, all involved in the Fragment between the control display and so on, should be entrusted to the host Activity for unified management.

Therefore, it is highly recommended that some external operations of Fragment be passed to the host Activity in the form of an open interface. The specific implementation is as follows:

 Public  class onefragment extends Fragment implements View. Onclicklistener {     Public  interface ionefragmentclicklistener{        voidOnonefragmentclick (); }@Nullable    @Override     PublicViewOncreateview(Layoutinflater inflater, @Nullable viewgroup container, @Nullable Bundle savedinstancestate) {View Contentview = inflater.inflate (R.layout.fragment_one,NULL); Contentview.findviewbyid (R.id.edt_one). Setonclicklistener ( This);returnContentview; }@Override     Public void OnClick(View v) {if(Getactivity ()instanceofIonefragmentclicklistener) {((Ionefragmentclicklistener) getactivity ()). Ononefragmentclick (); }    }}

As long as the host activity implements Fragment defined external interface Ionefragmentclicklistener, the function of Fragment invoke activity can be realized.

Of course, you can do this:

 Public  class onefragment extends Fragment implements View. Onclicklistener {    PrivateIonefragmentclicklistener Clicklistener; Public  interface ionefragmentclicklistener{        voidOnonefragmentclick (); } Public void Setclicklistener(Ionefragmentclicklistener Clicklistener) { This. Clicklistener = Clicklistener; }@Nullable    @Override     PublicViewOncreateview(Layoutinflater inflater, @Nullable viewgroup container, @Nullable Bundle savedinstancestate) {View Contentview = inflater.inflate (R.layout.fragment_one,NULL); Contentview.findviewbyid (R.id.edt_one). Setonclicklistener ( This);returnContentview; }@Override     Public void OnClick(View v)    {Clicklistener.ononefragmentclick (); }}

The principle is the same, but in comparison with the first method, you need to add additional listening settings to the host Activity:

oneFragment.setClickListener(this);
Getactivity () Reference issue

In use, it is common to getActivity() get to the host Activity object in Fragment, but the following two problems are caused by a slight carelessness:

First, an instance of the Activity destroys the problem. For example, there are asynchronous time-consuming tasks such as network requests in Fragment, and when the task executes the callback Fragment method and uses it to the host activity object, it is likely that the host activity object has been destroyed, causing Nullpointexception and other anomalies, even caused the program to crash. Therefore, the asynchronous callback needs to be aware of the addition of null values such as judgment (such as: Fragment.isadd (), getactivity ()!=null, etc.), or in the fragment to create the instance by getActivity().getApplicationContext() means of the method to save the entire application context object, and then to use;

Second, a memory leak issue. If Fragment holds a reference to the host activity, it causes the host activity to not be recycled, causing a memory leak. So, if possible, try not to hold a reference to the host Activity in the Fragment.

In order to solve the problem of context reference, Fragment provides a Onattach (context) method in which we can get to the context object, such as:

@OverridepublicvoidonAttach(Context context) {    super.onAttach(context);    this.context = context;}
Fragment overlap problem

Before we introduce Fragment initialization, we refer to the problem of activity destruction and reconstruction, just imagine that when the activity re-executes the OnCreate () method, will it perform the Fragment creation and display again? And the Fragment instance that was already in existence will also be destroyed and created again, does this not coincide with the second creation of the Fragment in the OnCreate () method in the Activity, and then the UI overlap problem?

Based on experience, we usually set Activity to landscape mode in androidmanifest, so this problem does not occur due to screen rotation. A more likely occurrence is that the application is in the background for a long time, but because the device memory is tight, the Activity is destroyed and Fragment overlap occurs when the user opens the app again. However, this problem is difficult to meet in the development phase due to the frequent use of the application, but it does exist. Therefore, the development process, we must pay attention to such problems.

Once you know the root cause of the problem, the corresponding solution is there. is to create a Fragment instance in Activity, add a judgment, there are three ways to handle it:

The first approach is handled in the Onattachfragment () method provided by the Activity:

@OverridepublicvoidonAttachFragment(Fragment fragment) {    super.onAttachFragment(fragment);    ifinstanceof  OneFragment){        oneFragment = (OneFragment) fragment;    }}

The second way, before you create a Fragment, you add a judgment to determine if it already exists:

Fragment tempFragment = getSupportFragmentManager().findFragmentByTag("OneFragment");if (tempFragment==null) {    oneFragment = OneFragment.newInstance();    "OneFragment");}else {    oneFragment = (OneFragment) tempFragment;}

The third way, more simple, directly using savedinstancestate judgment can:

if (savedInstanceState==null) {    oneFragment = OneFragment.newInstance();    "OneFragment");}else {    oneFragment = (OneFragment) getSupportFragmentManager().findFragmentByTag("OneFragment");}
Onactivityresult ()

The Fragment class provides a Startactivityforresult () method for page jumps and data callbacks between activity, in fact, the corresponding method of invoking activity. However, it is important to note that Fragment does not provide a setresult () method when the page is returned, which can be implemented by the host Activity.

For example, in Fragmenta inside the Activitya call Startactivityforresult () to jump to Activityb, and activityb inside Fragmentb return to Activitya, return code As follows:

new Intent();// putExtragetActivity().setResult(Activity.RESULT_OK, intent);getActivity().finish();

At callback, the Onactivityresult () method in Activitya is first recalled, and then the Onactivityresult () method in the callback Fragmenta is distributed, as can be seen from the source code of the Fragmentactivity class:

/*** Dispatch Incoming result to the correct fragment.*/@Overrideprotected void Onactivityresult(intRequestcode,intResultCode, Intent data) {mfragments.notestatenotsaved ();intRequestindex = requestcode>> -;if(Requestindex! =0) {requestindex--;        String who = Mpendingfragmentactivityresults.get (Requestindex); Mpendingfragmentactivityresults.remove (Requestindex);if(who = =NULL) {LOG.W (TAG,"Activity result delivered for unknown Fragment.");return; } Fragment targetfragment = mfragments.findfragmentbywho (WHO);if(Targetfragment = =NULL) {LOG.W (TAG,"Activity result no fragment exists for who:"+ WHO); }Else{Targetfragment.onactivityresult (Requestcode &0xFFFF, ResultCode, data); }return; }Super. Onactivityresult (Requestcode, ResultCode, data);}

Further, if Fragmenta is embedded in a layer of fragmentaa and then jumps from Fragmentaa to Activityb, can I receive a callback in Fragmentaa () Obviously not. From the above source can be seen fragmentactivity only to a level of distribution. Therefore, if you want to achieve multi-level distribution, you have to manually add the distribution code in all levels of Fragment, to the next level of Fragment.

State change Monitoring

State transitions such as hide and show in Fragment will be reflected in the corresponding callback functions, which we can use to do some functions such as interface refresh. One of the more common listening functions is the onhiddenchanged () method, which directly affects the return value of the Ishidden () method.

In addition to the Ishidden () method, there is also a isVisible () method, which is also used to determine the state of the Fragment, indicating whether Fragment is visible to the user, and if true, the three-point condition must be met: 1,fragment has been added to Activit Y; 2, the view content has been linked to the window; 3. is not hidden, that is, Ishidden () is false. These three points, from the source code of IsVisible () can be seen:

/*** Return true if the fragment is currently visible to the user.  This means* it: (1) has been added, (2) has its view attached to the window, and * (3) is not hidden.*/finalpublicbooleanisVisible() {    returnnull        null && mView.getVisibility() == View.VISIBLE;}

Note: the onhiddenchanged () method can listen for the Hide () and show () operations, which differs from the Setuservisiblehint () method, where the common occurrence scenario is Fragment in Viewpager and Fragment combinations Used in Pageradapter. Viewpager sliding is through this method to change the state of Fragment, using this method can be implemented Fragment lazy loading, subsequent articles in detail to describe the implementation.

Reference links

From the above introduction can be seen, although the use of Fragment is very convenient, but there are a lot of problems, with a long time you will find that there is no stepping up the pit waiting for you. Of course, each pit has a corresponding solution, Google, everywhere, always find what you need. These series of articles, for example, are filled with dry goods:

    • Android fragment full parsing, everything you need to know about fragmentation

    • Android Fragment everything you should know

    • Fragment Full Analytic series (i): The pits that have been trampled for years

This article was created by Maple and started Yi Fengfeng's personal blog, the simultaneous authorization of the public Number: technical Bird (Niaotech).

Welcome to all forms of communication and reprint, annotated author and source can be.

The title of this article is: Use of Android Fragment, some precautions you should know

This article links to: http://yifeng.studio/2016/12/15/android-fragment-attentions/

The use of Android Fragment, some of the things you should be aware of

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.