Android Fragment everything you should know, AndroidFragment

Source: Internet
Author: User

Android Fragment everything you should know, AndroidFragment

Reprinted please indicate the source: bytes]

I wrote two Fragment introductions a long time ago, mainly about its functions: the real full parsing of Android Fragment (on) and the real full parsing of Android Fragment (below) if you are interested, take a look. How to Use Fragment in previous blogs. This article aims to teach you how to use Fragment well, that is, some suggestions for using Fragment. (most of the content is from android programming the big nerd ranch guide, baidu, you know, although it is a basic book, it is worth reading ).

1. Overview

First of all, let's briefly review it. I believe everyone is familiar with Fragment. For Fragment usage, on the one hand, the Activity needs to arrange the location for Fragment in the layout, and on the other hand, it needs to manage the Fragment lifecycle. There is a FragmentManager in the Activity, which maintains the fragment queue internally and the rollback stack of the fragment transaction.

In general, Fragment is added in the Activity as follows:

public class MainActivity extends FragmentActivity{private ContentFragment mContentFragment  ; @Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FragmentManager fm = getSupportFragmentManager();mContentFragment = (ContentFragment) fm.findFragmentById(R.id.id_fragment_container);if(mContentFragment == null ){mContentFragment = new ContentFragment();fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();}}}

For the above code, I asked two questions:

1. Why is null required?

This is mainly because when the Activity is re-created because of a configuration change (screen rotation) or insufficient memory, our fragment will be saved, but a new FragmentManager will be created, the new FragmentManager will first retrieve the saved fragment queue and recreate the fragment queue to restore the previous status.

2. What is the role of the layout id in add (R. id. id_fragment_container, mContentFragment?

On the one hand, it is to inform FragmentManager of the location of the fragment; on the other hand, it is the unique identifier of the fragment; just like we found it through fm. findFragmentById (R. id. id_fragment_container ~~

Now, I have briefly reviewed the basic usage. For details, refer to the above blog or other materials. Next, I will introduce some usage suggestions ~~


2. Fragment Arguments

The following describes a simple scenario. For example, if a button triggers an Activity jump and a parameter needs to be passed to the Fragment of the target Activity through Intent, how can this Fragment obtain the current Intent value?

Some guys will say, is this simple? View my code (problem code ):

public class ContentFragment extends Fragment{private String mArgument ; public static final String ARGUMENT ="argument";@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);mArgument = getActivity().getIntent().getStringExtra(ARGUMENT);}

We get the host Activty directly in the onCreate of Fragment. The host Activity will certainly get the Intent through getIntent, and then get the parameter at will through the get method ~~

In this way, the function is implemented,? There is a big problem: a major reason for using Fragment is to reuse it. This is equivalent to the fact that this Fragment has been fully bound to the current host Activity, and reuse directly wastes ~~~ So? We recommend that you use arguments to create Fragment.

Public class ContentFragment extends Fragment {private String mArgument; public static final String ARGUMENT = "argument"; @ Overridepublic void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // mArgument = getActivity (). getIntent (). getStringExtra (ARGUMENT); Bundle bundle = getArguments (); if (bundle! = Null) mArgument = bundle. getString (ARGUMENT);}/*** input the required parameter and set it to arguments * @ param argument * @ return */public static ContentFragment newInstance (String argument) {Bundle bundle = new Bundle (); bundle. putString (ARGUMENT, argument); ContentFragment contentFragment = new ContentFragment (); contentFragment. setArguments (bundle); return contentFragment ;}

Add the newInstance method to Fragment, pass in the required parameters, set them to bundle, setArguments (bundle), and get them in onCreate;

This completes the decoupling between Fragment and Activity. Note:

The setArguments method must be added to the Activity after the fragment is created. Do not call add first, and then set arguments.


3. startActivityForResult of Fragment

It is still a simple scenario: Two Fragment, one Fragment that displays the list of articles (called ListTitleFragment), and the other Fragment that displays details (called ContentFragment). Of course, both Fragment have their own host Activity.

Now, we click the list items in the Fragment list and input the corresponding parameters to display the detailed information of Fragment. On the details page, you can make comments, after you click back, the previous comments are displayed in the Fragment list;

That is to say, if we click to jump to the Fragment of the corresponding Activity and want it to return parameters, we must use Fragment. startActivityForResult;

The startActivityForResult () and onActivityResult () methods exist in Fragment. However, there is no setResult () method, which is used to set the returned intent. In this way, we need to call getActivity (). setResult (ListTitleFragment. REQUEST_DETAIL, intent );.

Code details:

ListTitleFragment

public class ListTitleFragment extends ListFragment{public static final int REQUEST_DETAIL = 0x110;private List<String> mTitles = Arrays.asList("Hello", "World", "Android");private int mCurrentPos ; private ArrayAdapter<String> mAdapter ; @Overridepublic void onActivityCreated(Bundle savedInstanceState){super.onActivityCreated(savedInstanceState);setListAdapter(mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mTitles));}@Overridepublic void onListItemClick(ListView l, View v, int position, long id){mCurrentPos = position ; Intent intent = new Intent(getActivity(),ContentActivity.class);intent.putExtra(ContentFragment.ARGUMENT, mTitles.get(position));startActivityForResult(intent, REQUEST_DETAIL);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data){Log.e("TAG", "onActivityResult");super.onActivityResult(requestCode, resultCode, data);if(requestCode == REQUEST_DETAIL){mTitles.set(mCurrentPos, mTitles.get(mCurrentPos)+" -- "+data.getStringExtra(ContentFragment.RESPONSE));mAdapter.notifyDataSetChanged();}}}


ContentFragment
public class ContentFragment extends Fragment{private String mArgument;public static final String ARGUMENT = "argument";public static final String RESPONSE = "response";@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);Bundle bundle = getArguments();if (bundle != null){mArgument = bundle.getString(ARGUMENT);Intent intent = new Intent();intent.putExtra(RESPONSE, "good");getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);}}public static ContentFragment newInstance(String argument){Bundle bundle = new Bundle();bundle.putString(ARGUMENT, argument);ContentFragment contentFragment = new ContentFragment();contentFragment.setArguments(bundle);return contentFragment;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){Random random = new Random();TextView tv = new TextView(getActivity());tv.setText(mArgument);tv.setGravity(Gravity.CENTER);tv.setBackgroundColor(Color.argb(random.nextInt(100),random.nextInt(255), random.nextInt(255), random.nextInt(255)));return tv;}}

We have pasted two Fragment codes, and we can see the code in ListTitleFragment. onListItemClick, use startActivityForResult () to jump to the target Activity, get the parameter in the Fragment (ContentFragment) of the target Activity, and then call getActivity (). setResult (ListTitleFragment. REQUEST_DETAIL, intent); set the returned data; finally, in ListTitleFragment. onActivityResult () returns the returned data for ECHO;

It provides a solution for you to encounter similar problems in the future. It also illustrates a problem: fragment can receive returned results from the Activity, but its own settings cannot generate returned results, only the Activity has returned results.

Next I will post the two Fragment host activities:

ListTitleActivity

public class ListTitleActivity extends FragmentActivity{private ListTitleFragment mListFragment;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_single_fragment);FragmentManager fm = getSupportFragmentManager();mListFragment = (ListTitleFragment) fm.findFragmentById(R.id.id_fragment_container);if(mListFragment == null ){mListFragment = new ListTitleFragment();fm.beginTransaction().add(R.id.id_fragment_container,mListFragment).commit();}}}


ContentActivity:

public class ContentActivity extends FragmentActivity{private ContentFragment mContentFragment;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_single_fragment);FragmentManager fm = getSupportFragmentManager();mContentFragment = (ContentFragment) fm.findFragmentById(R.id.id_fragment_container);if(mContentFragment == null ){String title = getIntent().getStringExtra(ContentFragment.ARGUMENT);mContentFragment = ContentFragment.newInstance(title);fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();}}}

Have you found that the code in the two activities is extremely similar and the same layout file is used:

Activity_single_fragment.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"android:id="@+id/id_fragment_container"></RelativeLayout>

Why do I need to paste this Acticity code? In our project, if we use Fragment in principle, we will find a lot of similar code, so we can abstract an Activity and host our Single Fragment.

For details, see the next section.


4. SingleFragmentActivity

The abstracted Activity code is:

package com.example.demo_zhy_23_fragments;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;public abstract class SingleFragmentActivity extends FragmentActivity{protected abstract Fragment createFragment();@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_single_fragment);FragmentManager fm = getSupportFragmentManager();Fragment fragment =fm.findFragmentById(R.id.id_fragment_container);if(fragment == null ){fragment = createFragment() ;fm.beginTransaction().add(R.id.id_fragment_container,fragment).commit();}}}

So, with this SingleFragmentActivity, our ContentActivity and ListTitleActivity can also be transformed ~

package com.example.demo_zhy_23_fragments;import android.support.v4.app.Fragment;public class ContentActivity extends SingleFragmentActivity{private ContentFragment mContentFragment;@Overrideprotected Fragment createFragment(){String title = getIntent().getStringExtra(ContentFragment.ARGUMENT);mContentFragment = ContentFragment.newInstance(title);return mContentFragment;}}

package com.example.demo_zhy_23_fragments;import android.support.v4.app.Fragment;public class ListTitleActivity extends SingleFragmentActivity{private ListTitleFragment mListFragment;@Overrideprotected Fragment createFragment(){mListFragment = new ListTitleFragment();return mListFragment;}}

Is it much more concise? I believe Fragment projects are preferred. There are many similar activities. Use SingleFragmentActivity to simplify your code ~~

Well, this code is from the book that the article began to recommend. I recommend it again ~~.


5. FragmentPagerAdapter and FragmentStatePagerAdapter

I believe that we are familiar with the two PagerAdapter subclasses ~~ Since the advent of Fragment, ViewPager has been used in combination with any of the above examples to create an APP homepage ~~~

So what are the differences between the two classes?

The main difference lies in whether fragment is destroyed. the following details:

FragmentPagerAdapter: For fragment that is no longer needed, you can call the detach method to destroy only the view and will not destroy the fragment instance.

FragmentStatePagerAdapter: fragment that is no longer needed will be destroyed. After the current transaction is committed, fragmeng will be completely removed from the FragmentManager of the current Activity. The state indicates that the fragmeng will be destroyed, saves the Bundle information in the onSaveInstanceState (bundle outState). When the user switches back, the bundle can be used to resume the generation of a new fragment. That is, you can call onSaveInstanceState (Bundle outState) method to save some data and resume the creation in onCreate.

As mentioned above, using the FragmentStatePagerAdapter saves more memory, but it takes time to destroy the new one. Generally, If you create three or four tabs on the home page, you can use the FragmentPagerAdapter. If you use ViewPager to display a large number of entries, we recommend that you use the FragmentStatePagerAdapter.

We will not write down the specific case because of the length of the Article. We will test it on our own.


6. data transmission between Fragment

As shown in figure 3 above, data transmission between two Fragment is normal.

Another special case is that two Fragment instances are in the same Activity. For example, click the current Fragment button to bring up a dialog box (DialogFragment ), in the dialog box, operations must be returned to the triggered Fragment. How can we transmit data? Recommended for dialog box usage: Android official recommendation: DialogFragment creation dialog box

Let's continue to modify our code: ListTitleFragment and ContentFragment. Add a dialog box: EvaluateDialog. When you click the ContentFragment content, a comment list is displayed. The user selects the comment.

Now our focus is on how to elegantly get the comments returned by EvaluateDialog in ContentFragment:

Remember that in an Activity, we certainly do not use startActivityForResult; but the data we return is still received in onActivityResult.

Let's take a look at the Code:

ContentFragment

Public class ContentFragment extends Fragment {private String mArgument; public static final String ARGUMENT = "argument"; public static final String RESPONSE = "response"; public static final String EVALUATE_DIALOG = "evaluate_dialog "; public static final int REQUEST_EVALUATE = 0X110 ;//... @ Overridepublic View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {Random random = new Random (); TextView TV = new TextView (getActivity (); ViewGroup. layoutParams params = new ViewGroup. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); TV. setLayoutParams (params); TV. setText (mArgument); TV. setGravity (Gravity. CENTER); TV. setBackgroundColor (Color. argb (random. nextInt (100), random. nextInt (255), random. nextInt (255), random. nextInt (255); // set clicktv. setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {EvaluateDialog dialog = new EvaluateDialog (); // note setTargetFragmentdialog. setTargetFragment (ContentFragment. this, REQUEST_EVALUATE); dialog. show (getFragmentManager (), EVALUATE_DIALOG) ;}); return TV ;}// receives the returned data @ Overridepublic void onActivityResult (int requestCode, int resultCode, Intent data) {super. onActivityResult (requestCode, resultCode, data); if (requestCode = REQUEST_EVALUATE) {String evaluate = data. getStringExtra (EvaluateDialog. RESPONSE_EVALUATE); Toast. makeText (getActivity (), evaluate, Toast. LENGTH_SHORT ). show (); Intent intent = new Intent (); intent. putExtra (RESPONSE, evaluate); getActivity (). setResult (ListTitleFragment. REQUEST_DETAIL, intent );}}}

Some irrelevant code has been deleted. Note that we have added a click event to textview in onCreateView to bring up our dialog. Pay attention to a line of code:

Dialog. setTargetFragment (ContentFragment. this, REQUEST_EVALUATE );

We have called Fragment. setTargetFragment. This method is generally used for starting the current fragment by another fragment. After the operation is completed, data is returned, which meets our needs ~~~ Note: This sentence is very important.

Next, let's look at the EvaluateDialog code:

Package com. example. demo_zhy_23_fragments; import android. app. activity; import android. app. alertDialog; import android. app. dialog; import android. content. dialogInterface; import android. content. dialogInterface. onClickListener; import android. content. intent; import android. OS. bundle; import android. support. v4.app. dialogFragment; public class EvaluateDialog extends DialogFragment {private String [] mEvaluteVals = new String [] {"GOOD", "BAD", "NORMAL "}; public static final String RESPONSE_EVALUATE = "response_evaluate"; @ Overridepublic Dialog onCreateDialog (Bundle savedInstanceState) {AlertDialog. builder builder = new AlertDialog. builder (getActivity (); builder. setTitle ("Evaluate :"). setItems (mEvaluteVals, new OnClickListener () {@ Overridepublic void onClick (DialogInterface dialog, int which) {setResult (which) ;}}); return builder. create ();} // sets the returned data protected void setResult (int which) {// determines whether targetFragmentif (getTargetFragment () = null) return is set; intent intent = new Intent (); intent. putExtra (RESPONSE_EVALUATE, mEvaluteVals [which]); getTargetFragment (). onActivityResult (ContentFragment. REQUEST_EVALUATE, Activity. RESULT_ OK, intent );}}

The focus is to check the setResult after the click. We first determine whether targetFragment is set. If so, we will return some data to targetFragment.

We created intent to encapsulate the data to be transmitted, and finally manually called onActivityResult to return the data ~~

Finally, we can receive the onActivityResult in ContentFragment.


OK. Finally, we have put these tips together. At this point, our Fragment's recommended usage is over ~~~ Then, the following source code is provided:






Download source code




I have created a QQ Group for your convenience. Group Number:423372824

Bytes ----------------------------------------------------------------------------------------------------------

Some of the bloggers have already been online. If you do not like boring text, stamp it (for initial record, we look forward to your support ):

1. Use of a hundred-degree map in Android

2. scratch cards for Android custom controls in e-commerce activities

3. Android custom controls create Android streaming layout and popular labels

4. Implementation of Android intelligent robot xiaomu

5. High imitation QQ5.0 slide

6. High imitation 5.2.1 main interface and message reminder






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.