# FragmentMenu **Repository Path**: amqr/FragmentMenu ## Basic Information - **Project Name**: FragmentMenu - **Description**: 记录Fragment声明周期,避免重复创建,每个Fragment独立拥有Toobar和menu - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2016-11-26 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README >Toorbar现在已经被广泛使用了,但是多个Fragment之间使用Toorbar的使用可能会遇到menu消失的问题,单就本来这点不必成文,但是一想到好像还没有写过关Fragment声明周期的和复用的文章,就干脆记录一下算了,后面如果需要拿起来参考也算可以。 文章分三点进行描述,第一点说的是Fragment的生命周期,大可忽略之,第二点说的是如何利用add和hide避免重复创建Fragment,老生常谈也可忽略之,第三点说是让每一个Toolbar对应不同的Toolbar的menu,这个还是可以稍微参考一下的。 # 一、以事务replace方式简述生命周期 先上图,再代码,后分析 ![gif依次12341.gif](http://upload-images.jianshu.io/upload_images/1083096-b168782195ee38e8.gif?imageMogr2/auto-orient/strip) 上代码 Activity ``` public class StyleFirstActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener { private RadioGroup mRbTab; private RadioButton mRbOne; private RadioButton mRbTwo; private RadioButton mRbThree; private RadioButton mRbFour; private OneFragment oneFragment; private TwoFragment twoFragment; private ThreeFragment threeFragment; private FourFragment fourFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRbTab = (RadioGroup) findViewById(R.id.mRbTab); mRbOne = (RadioButton) findViewById(R.id.mRbOne); mRbTwo = (RadioButton) findViewById(R.id.mRbTwo); mRbThree = (RadioButton) findViewById(R.id.mRbThree); mRbFour = (RadioButton) findViewById(R.id.mRbFour); mRbTab.setOnCheckedChangeListener(this); commitOneFrag(); } // MainActivty实现接口的必须复写的方法 @Override public void onCheckedChanged(RadioGroup group, int checkedId) { FragmentManager fm = getSupportFragmentManager(); // getSupportFragmentManager(); 才是v4的 FragmentTransaction transaction = fm.beginTransaction(); // Fragment的事务 switch (checkedId) { case R.id.mRbOne: if (oneFragment == null) { oneFragment = new OneFragment(); } transaction.replace(R.id.mFlWaitReplace, oneFragment); break; case R.id.mRbTwo: if (twoFragment == null) { twoFragment = new TwoFragment(); } transaction.replace(R.id.mFlWaitReplace, twoFragment); break; case R.id.mRbThree: if (threeFragment == null) { threeFragment = new ThreeFragment(); } transaction.replace(R.id.mFlWaitReplace, threeFragment); break; case R.id.mRbFour: if (fourFragment == null) { fourFragment = new FourFragment(); } transaction.replace(R.id.mFlWaitReplace, fourFragment); break; } transaction.commit(); } private void commitOneFrag() { OneFragment oneFrag = new OneFragment(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.mFlWaitReplace, oneFrag); ft.commit(); } } ``` 布局文件 ``` ``` . . . Fragment,四个都类似,以为OneFragmemt为例子 ``` public class OneFragment extends Fragment { private View rootView; @Nullable @Override public View onCreateView(LayoutInflater infater, ViewGroup container, Bundle savedInstanceState) { Log.d(GeneralConst.TAG,"OneFragment --- onCreateView"); rootView = View.inflate(getActivity(), R.layout.fragment_one, null); initView(); return rootView; } private void initView() { rootView.findViewById(R.id.mTvOne).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getActivity(),"FragmentOne的Tv点击",Toast.LENGTH_SHORT).show(); } }); } @Override public void onAttach(Context context) { super.onAttach(context); Log.d(GeneralConst.TAG,"OneFragment --- onAttach"); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(GeneralConst.TAG,"OneFragment --- onCreate"); } @Override public void onStart() { super.onStart(); Log.d(GeneralConst.TAG,"OneFragment --- onStart"); } @Override public void onResume() { super.onResume(); Log.d(GeneralConst.TAG,"OneFragment --- onResume"); } @Override public void onPause() { super.onPause(); Log.d(GeneralConst.TAG,"OneFragment --- onPause"); } @Override public void onStop() { super.onStop(); Log.d(GeneralConst.TAG,"OneFragment --- onStop"); } @Override public void onDestroyView() { super.onDestroyView(); Log.d(GeneralConst.TAG,"OneFragment --- onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); Log.d(GeneralConst.TAG,"OneFragment --- onDestroy"); } @Override public void onDetach() { super.onDetach(); Log.d(GeneralConst.TAG,"OneFragment --- onDetach"); } } ``` Fragment和Activity的生命周期较为相似了。 只是Fragment有几个Activity中没有的新方法,这里需要重点介绍一下: * onAttach方法:Fragment和Activity建立关联的时候调用。 * onCreateView方法:为Fragment加载布局时调用。 * onActivityCreated方法:当Activity中的onCreate方法执行完后调用。 * onDestroyView方法:Fragment中的布局被移除时调用。 * onDetach方法:Fragment和Activity解除关联的时候调用。 进入该Activity,依次点击第一,第二,第三,第四,第一个Fragment 现在对点击进行分析: 执行了5个生命周期方法,对比其他的这里只是,这里这是执行了5个,原因是因为我们一进入这个Activity默认就进入了第一个Activity,然后我们再次点击了第一个,相当于重复点击了两次第一个。 ``` 11-23 08:30:28.712 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onAttach 11-23 08:30:28.712 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreate 11-23 08:30:28.712 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreateView 11-23 08:30:28.712 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onStart 11-23 08:30:28.712 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onResume --- 分割线 --- 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onAttach 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreate 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onPause 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onStop 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDestroyView 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDestroy 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDetach 11-23 08:30:31.269 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreateView 11-23 08:30:31.270 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onStart 11-23 08:30:31.270 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onResume --- 分割线 --- 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onAttach 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onCreate 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onPause 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onStop 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDestroyView 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDestroy 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onDetach 11-23 08:30:32.350 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onCreateView 11-23 08:30:32.351 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onStart 11-23 08:30:32.351 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onResume --- 分割线 --- 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onAttach 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onCreate 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onPause 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onStop 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onDestroyView 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onDestroy 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: TwoFragment --- onDetach 11-23 08:30:33.033 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onCreateView 11-23 08:30:33.035 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onStart 11-23 08:30:33.035 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onResume --- 分割线 --- 11-23 08:30:33.699 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onAttach 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onCreate 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onPause 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onStop 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onDestroyView 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onDestroy 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: ThreeFragment --- onDetach 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onCreateView 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onStart 11-23 08:30:33.700 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onResume --- 分割线 --- 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onAttach 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreate 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onPause 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onStop 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onDestroyView 11-23 08:30:34.833 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onDestroy 11-23 08:30:34.834 11279-11279/com.amqr.testfragment D/FragTest: FourFragment --- onDetach 11-23 08:30:34.834 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onCreateView 11-23 08:30:34.839 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onStart 11-23 08:30:34.839 11279-11279/com.amqr.testfragment D/FragTest: OneFragment --- onResume ``` 如上,我们看的出来,以这种方式构建,每次点击切换到一个Fragment,至少都会执行5个方法 ``` onAttach onCreate onCreateView onStart onResume ``` 如果是切换那么会相应交织着上一个被销毁的过程(正因为上一个被销毁,所以我们点击新的Fragment才会有重新创建) 这里关键是明白一点,我们这里的新切换的Fragment都会有一个onCreate和onCreateView过程,这在大多数情况下不是我们想要的,对于页面复杂的Fragment是比较消耗内存的,这不是我们想看到的。 产生这个问题的主要原因是我们采用了replace()方法来替换Fragment。 关于这个老生常谈的问题就到此为止。 > 关于Fragment生命周期可以参考[Android Fragment完全解析,关于碎片你所需知道的一切](http://blog.csdn.net/sinyu890807/article/details/8881711) # 二、利用事务的add和hide复用Fragment 一样,一图二码三分析 ![复用12341332.gif](http://upload-images.jianshu.io/upload_images/1083096-8db059534feec221.gif?imageMogr2/auto-orient/strip) Activity ``` public class StyleSecondActivity extends AppCompatActivity{ private Button[] mTabs; // ======== 四个TAB private OneFragment sOneFragment; private TwoFragment sTwoFragment; private ThreeFragment sThreeFragment; private FourFragment sFourFragment; private Fragment[] fragments; private int index; private int currentTabIndex; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_style_second); mTabs = new Button[4]; mTabs[0] = (Button) findViewById(R.id.mBtOneFragment); mTabs[1] = (Button) findViewById(R.id.mBtTwoFragment); mTabs[2] = (Button) findViewById(R.id.mBtThreeFragment); mTabs[3] = (Button) findViewById(R.id.mBtFourFragment); // select first tab mTabs[0].setSelected(true); // 实例化Tab sOneFragment = new OneFragment(); sTwoFragment = new TwoFragment(); sThreeFragment = new ThreeFragment(); sFourFragment = new FourFragment(); fragments = new Fragment[]{sOneFragment, sTwoFragment, sThreeFragment, sFourFragment}; // 一开始只把 第一个 和 第二个 Fragment添加到事务里面,(方便切换时有数据) // 然后默认展示第一个,第二个隐藏起来 getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, sOneFragment) .add(R.id.fragment_container, sTwoFragment).hide(sTwoFragment).show(sOneFragment) .commit(); } /** * 每一个按钮都带有android:onClick="onTabClicked" * 不采用常规的复写onClick而采用这种方式,是为了统一操作这些按钮 * @param view */ public void onTabClicked(View view) { switch (view.getId()) { case R.id.mBtOneFragment: index = 0; break; case R.id.mBtTwoFragment: index = 1; break; case R.id.mBtThreeFragment: index = 2; break; case R.id.mBtFourFragment: index = 3; break; } if (currentTabIndex != index) { // 切换了Fragment FragmentTransaction trx = getSupportFragmentManager().beginTransaction(); trx.hide(fragments[currentTabIndex]); // 隐藏原来的 if (!fragments[index].isAdded()) { // 如果当前的没有被添加到FragmentTransaction,添加之 trx.add(R.id.fragment_container, fragments[index]); } trx.show(fragments[index]).commit(); // 添加事务,切换Fragment } mTabs[currentTabIndex].setSelected(false); mTabs[index].setSelected(true); currentTabIndex = index; } } ``` 布局文件 ```