Android (10) --- Fragment-Fragment communication and ListFragment and androidfragment
I. Preface
The first two blogs introduced the basic usage of fragment.
1. Fragment API Introduction: such as FragmentManager and FragmentTransaction.
2. Definition method: Inherit the Fragment class and override onCreat, onCreatView, onPause, and so on.
3. Reference Method: dynamically add fragment by defining the <Fragment> label or adding () of the FragmentTrasaction instance.
4. Fragment rollback stack and Fragment lifecycle.
The remaining important knowledge points of Fragment are almost the same:
1. Communication between Fragment and Activity, Fragment and Fragment.
2. Use ListFragment.
3. Other related fragmented knowledge points.
This blog begins to record the three points mentioned above. The introduction to Fragment is over.
2. Fragment Communication
A. Fragment communicates with Activity
We usually manage the Fragment in the Activity, so generally the Activity should have reference to all its affiliated Fragment, then, you can directly access the Fragment method through the instantiated Fragment object in the Activity. Let's look at a simple piece of code:
package com.example.fragmenttransdemo;import android.app.Activity;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.os.Bundle;public class MainActivity extends Activity {private FragmentManager fm;private FragmentTransaction ftx;private FragmentLeft fLeft;private FragmentRight fRight;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);fm = getFragmentManager();ftx = fm.beginTransaction();fLeft = new FragmentLeft();fRight = new FragmentRight();ftx.add(R.id.fm_left, fLeft, "left");ftx.add(R.id.fm_right, fRight, "right");ftx.commit();}}
So what if there is no reference to Fragment in the Activity? For example, if we use the <fragment> label to introduce fragment in the layout file of the Activity, the answer is also very simple, as mentioned in the first API, you can specify an id or tag for each fragment. You can find the specified Fragment by using the FragmentManager instance method: findFragmentById or findFragmentByTag. For example:
Layout File Code
<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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.fragmentbasedemo.MainActivity" > <fragment android:id="@+id/fm_one" android:name="com.example.fragmentbasedemo.FragmentOne" android:layout_width="match_parent" android:layout_height="match_parent" android:tag="fragment_one_tag" /></RelativeLayout>
Activity Code
package com.example.fragmentbasedemo;import android.app.Activity;import android.app.FragmentManager;import android.os.Bundle;import android.util.Log;import android.widget.Toast;public class MainActivity extends Activity {private static final String TAG = "MainActivity";private FragmentManager fm;private FragmentOne fOne;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.i(TAG, "onCreate");setContentView(R.layout.activity_main);fm = getFragmentManager();fOne = (FragmentOne) fm.findFragmentById(R.id.fm_one);String fOneTag = fOne.getTag();Toast.makeText(MainActivity.this, "fOneTag:\n" + fOneTag,Toast.LENGTH_LONG).show();}}
We can see that the id and tag are defined for fragment in the layout file, and the Fragment can be found through findFragmentById in the code, and the Fragment tag information can be obtained successfully:
After reading the Fragment operation in the Activity, let's take a look at how to operate the Activity to which it belongs in the Fragment. In the Fragment, call getActivity () you can obtain and operate the Activity bound to the current Fragment.
In addition to basic interaction, data transmission may also be required. There are two possible cases:
1. The Activity transmits data to Fragment (by Bundle)
Create a Bundle data packet in the Activity and call the setArguments (Bundle B) method Bundle data packet of Fragment to pass it to Fragment.
2. Fragment transmits data to the Activity (callback Interface)
The callback interface is described below.
B. Fragment communicates with Fragment
The simplest solution has been mentioned above. It also uses the findFragmentByTag of FragmentManager to find any Fragment of the same level. An example of a short piece of code is as follows:
Package com. example. fragmenttransdemo; import android. app. fragment; import android. app. fragmentManager; import android. OS. bundle; import android. view. layoutInflater; import android. view. view; import android. view. viewGroup; import android. widget. button; import android. widget. editText; import android. widget. toast; public class FragmentLeft extends Fragment {private Button button; private FragmentManager fm; @ Overridepublic void onCreate (Bundle savedInstanceState) {// TODO Auto-generated method stubsuper. onCreate (savedInstanceState) ;}@ Overridepublic View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// TODO Auto-generated method stubView = inflater. inflate (R. layout. left, null); button = (Button) view. findViewById (R. id. btn_left); button. setOnClickListener (new View. onClickListener () {@ Overridepublic void onClick (View v) {// TODO Auto-generated method stubfm = getFragmentManager (); // get FragmentFragment fRight = fm on the right. findFragmentByTag ("right"); View view = fRight. getView (); EditText et = (EditText) view. findViewById (R. id. et_right); String rightInfo = et. getText (). toString (); Toast. makeText (getActivity (), rightInfo, Toast. LENGTH_LONG ). show () ;}}); return view ;}@ Overridepublic void onPause () {// TODO Auto-generated method stubsuper. onPause ();}}
In FragmentLeft, first find the FragmentRight through the tag, then obtain the value in the Fragment layout and bring it up.
In addition to simple data search, we sometimes have operation requirements. For example, in the previous blog example, FragmentOne put a ListView and replaced the current Fragment when you click item, in the previous blog, my practice was to directly execute the replace method of FragmentManager in the OnItemClick event of ListView to replace it. Note that this is not desirable, no matter in the reference books of Android, this is also mentioned in Hongyang's blog: Fragment should be managed by Activity. Therefore, it is generally a standard practice: if you need to operate a Fragment, you should first define a callback interface within it, then implement this interface in the Activity and implement the abstract method of the interface, when Fragment operations are required, you can call back the implementation of the Activity in Fragment.
Next we will improve the example of the previous blog, which is also two Fragment. FragmentOne puts a ListView. When you click Item, replace Fragment and pass the value to the new Fragment. The first is the Fragment code:
Package com. example. fragmentbasedemo; import android. app. activity; import android. app. fragment; import android. OS. bundle; import android. view. layoutInflater; import android. view. view; import android. view. viewGroup; import android. widget. adapterView; import android. widget. adapterView. onItemClickListener; import android. widget. listView; public class FragmentTwo extends Fragment implements OnItemClickListener {Private ListView lv; @ Overridepublic void onAttach (Activity activity) {// TODO Auto-generated method stubsuper. onAttach (activity) ;}@ Overridepublic void onCreate (Bundle savedInstanceState) {// TODO Auto-generated method stubsuper. onCreate (savedInstanceState) ;}@ Overridepublic View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// TODO Auto-generated method stubV Iew v = inflater. inflate (R. layout. fragment_list, null); lv = (ListView) v. findViewById (R. id. lv_hero_list); lv. setOnItemClickListener (this); return v ;}@ Overridepublic void onPause () {// TODO Auto-generated method stubsuper. onPause () ;}@ Overridepublic void onItemClick (AdapterView <?> Parent, View view, int position, long id) {// determine whether the Activity has implemented this interface if (getActivity () instanceof MOnItemClickListener) (MOnItemClickListener) getActivity ()). onItemClick (view);} public interface MOnItemClickListener {void onItemClick (View view );}}
Let's look at the code in the Activity:
package com.example.fragmentbasedemo;import com.example.fragmentbasedemo.FragmentTwo.MOnItemClickListener;import android.app.Activity;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.TextView;public class MainActivity extends Activity implements MOnItemClickListener {private static final String TAG = "MainActivity";private FragmentManager fm;private FragmentTransaction ftx;private FragmentTwo fTwo;private FragmentThree fThree;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.i(TAG, "onCreate");setContentView(R.layout.activity_main);fm = getFragmentManager();ftx = fm.beginTransaction();fTwo = new FragmentTwo();ftx.add(R.id.fl_container, fTwo, "fragment_two");ftx.commit();}@Overridepublic void onItemClick(View view) {Bundle b = new Bundle();TextView tv = (TextView) view;b.putCharSequence("text", tv.getText());if (fThree == null) {fThree = new FragmentThree();fThree.setArguments(b);}fm = getFragmentManager();ftx = fm.beginTransaction();ftx.replace(R.id.fl_container, fThree, "fragment_three");ftx.commit();}}
The benefits of doing so are obvious, such:
1. Reduced the coupling between Activity and Fragment, and improved the Reuse Rate of Fragment.
2. You can directly manage any Fragment in the Activity.
3. Added program flexibility, which is also one of the benefits of decoupling. The interface must be processed and not implemented without processing.
4. Easy value transfer, such as the view parameter.
Iii. ListFragment
ListFragment is usually applicable to the Fragment of only one ListView. The reason for this is that ListFragment does not need to be laid out. You only need to provide an Adapter and use the setlistlistadapter (ListAdapter adapter Adapter) of ListFragment, it is very simple, without too much explanation. paste a sample code (the Activity code is not pasted, And the ListFragment can also be operated by Fragment ):
package com.wl.lfd;import java.util.ArrayList;import java.util.List;import android.app.ListFragment;import android.os.Bundle;import android.view.View;import android.widget.ArrayAdapter;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.Toast;public class MyListFragment extends ListFragment {private ListAdapter adapter;@Overridepublic void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);List<String> datas = new ArrayList<String>();for (int i = 0; i < 30; i++) {datas.add("druid" + i);}adapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, datas);setListAdapter(adapter);}@Overridepublic void onPause() {// TODO Auto-generated method stubsuper.onPause();}@Overridepublic void onListItemClick(ListView l, View v, int position, long id) {// TODO Auto-generated method stubToast.makeText(getActivity(), adapter.getItem(position).toString(),Toast.LENGTH_SHORT).show();}}
Below is:
Iv. Summary
The introduction to Fragment is all over, and we will continue to improve these Fragment articles in the future. This series of "Android for virgins" has come to an end, I am still thinking about what I will continue to learn later. Now I feel that I will have nothing to learn, and I am very annoyed. I am prepared to formulate a detailed and feasible learning plan and plan, come back and continue writing this series of blogs. There are still many things to learn. Continue to cheer up, Raito!