在开发中遇到一个很奇怪的问题,场景是MainActivity中有两个个Tab页,每个Tab页是一个Fragment。由于每个Fragment的Toolbar的menu都不一样。因此我为每个Fragment都创建一个Toolbar,并设置menu,其实现大体是这样的:
public class MyFragment extends Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
itoolbar.setTitle("");
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isMenuCreated) {
menu.clear();
inflater.inflate(R.menu.bookstore_menu, menu);
isMenuCreated = true;
mMenu = menu;
}
super.onCreateOptionsMenu(menu, inflater);
}
}
当两个Tab互相切换的时候,第一个Fragment中Toolbar的menu一直都能正常显示,第二个Fragment中Toolbar的menu只在第一次Fragment显示时才显示,之后切换Fragment就不显示了。为了查清这个问题,就整理了下Fragment中Toolbar上menu的创建过程,看看到底是什么原因引起的。
Fragment的每个操作都会调用BackStackRecord对象中的run方法
public void run() {
//根据当前的Op cmd,操作fragment
//cmd 包含:ADD,REPLACE,REMOVE,HIDE,SHOW,DETACH,ATTACH,
//因此每次Fragment切换调动这个方法
...
//调用FragmentManager的moveToState方法
mManager.moveToState(mManage.curState, transition,transitionStyle, true);
...
}
Fragment中的moveToState方法
public void moveToState(int newState, int transit, int transitStyle, boolean always) {
...
/**
* 当Fragment中设置setHasOptionsMenu(true)时,mNeedMenuInvalidate为true
* mHost是FragmentHostCallback实例,指向FragmentActivity的HostCallbacks内部类
*/
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
....
}
FragmentActivity的HostCallbacks类的onSupportInvalidateOptionsMenu方法
public void onSupportInvalidateOptionsMenu() {
FragmentActivity.this.supportInvalidateOptionsMenu();
}