我有一个 Activity ,我用一个按钮在两个 fragment (主要和设置)之间切换。在 MAIN fragment 中,我有一个包含 4 个子 fragment 的 ViewPager
。
起初运行一切正常,但如果我旋转屏幕,ViewPager
中 fragment 的 getActivity()
返回 null。
ActivityMain:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add or show the fragments
showHideScreenFragment(FRAGMENT_MAIN);
}
private void showHideScreenFragment(String tag) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
// Get the fragment from the backstack if it is existing
BaseFragment oldFragment = getFragmentFromBackstack(tag);
// Get the current fragment from the layout
BaseFragment currentFragment = getCurrentFragment();
if (oldFragment == null) {
if (currentFragment != null) {
ft.hide(currentFragment);
}
ft.add(getMainContainerId(), getFragmentInstance(tag), tag);
}
else {
if (currentFragment != null) {
if (isSameFragment(oldFragment, currentFragment))
return;
ft.hide(currentFragment);
}
if (oldFragment.isHidden())
ft.show(oldFragment);
}
ft.commit();
fm.executePendingTransactions();
}
private BaseFragment getFragmentInstance(String tag) {
if (tag.equals(FRAGMENT_MAIN)) return getFragmentMain();
if (tag.equals(FRAGMENT_SETTINGS)) return getFragmentSettings();
throw new RuntimeException("Fragment not found !");
}
private FragmentMain getFragmentMain() {
return new FragmentMain();
}
private FragmentSettings getFragmentSettings() {
return new FragmentSettings();
}
private BaseFragment getFragmentFromBackstack(String tag) {
if (tag.equals(FRAGMENT_MAIN)) return getFragmentMainFromBackstack();
if (tag.equals(FRAGMENT_SETTINGS)) return getFragmentSettingsFromBackstack();
throw new RuntimeException("Fragment not found !");
}
private FragmentMain getFragmentMainFromBackstack() {
return (FragmentMain) getSupportFragmentManager().findFragmentByTag(FRAGMENT_MAIN);
}
private FragmentSettings getFragmentSettingsFromBackstack() {
return (FragmentSettings) getSupportFragmentManager().findFragmentByTag(FRAGMENT_SETTINGS);
}
private boolean isSameFragment(Fragment f1, Fragment f2) {
return f1.getTag().equals(f2.getTag());
}
FragmentMain:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
// Add the 4 child fragments to the viewpager
populateViewPager();
// Debugging
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
_printFragmentStates();
}
}, 2500);
return view;
}
private void populateViewPager() {
ArrayList<BaseMainFragment> fragments = new ArrayList<BaseMainFragment>();
fragments.add(new FragmentSearch());
fragments.add(new FragmentFavorites());
fragments.add(new FragmentHouse());
fragments.add(new FragmentRoom());
adapterMain = new AdapterMain(getChildFragmentManager(), fragments);
viewPager.setOffscreenPageLimit(4);
viewPager.setAdapter(adapterMain);
}
// DEBUGGING
private void _printFragmentStates() {
Activity actSearch = null;
Activity actFav = null;
Activity actHouse = null;
Activity actRoom = null;
actSearch = getFragmentSearch().getActivity();
actFav = getFragmentFavorites().getActivity();
actHouse = getFragmentHouse().getActivity();
actRoom = getFragmentRoom().getActivity();
Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
Functions.logd("Main fragment act, is null: " + (getActivity() == null));
Functions.logd("Search act, is null: " + (actSearch == null));
Functions.logd("Favorite act, is null: " + (actFav == null));
Functions.logd("House act, is null: " + (actHouse == null));
Functions.logd("Room act, is null: " + (actRoom == null));
Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
private FragmentSearch getFragmentSearch() {
return (FragmentSearch) adapterMain.getItem(0);
}
private FragmentFavorite getFragmentFavorite() {
return (FragmentFavorite) adapterMain.getItem(1);
}
private FragmentHouse getFragmentHouse() {
return (FragmentHouse) adapterMain.getItem(2);
}
private FragmentRoom getFragmentHouse() {
return (FragmentRoom) adapterMain.getItem(3);
}
正如我所说,起初运行一切正常,但在我旋转屏幕后,我在 4 个子 fragment 中的 getActivity();
得到空值:Search、Favorite、House 和 Room .
Logcat 调试
1 次运行:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main fragment act, is null: false
Search act, is null: false
Favorite act, is null: false
House act, is null: false
Room act, is null: false
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
屏幕方向改变后:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main fragment act, is null: false
Search act, is null: true
Favorite act, is null: true
House act, is null: true
Room act, is null: true
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我做错了什么?
最佳答案
经过几个小时的调试,我发现如果您只有 1 个 fragment (没有子 fragment 或嵌套 fragment )附加到您的 Activity ,那么您不需要重新添加 fragment 。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add or show the fragments if the savedInstance is null, otherwise let the system reattach your fragment.
if (savedIstance == null)
showHideScreenFragment(FRAGMENT_MAIN);
}
你不需要重新附加 fragment ,android系统会为你做这件事。
而子 fragment 中getActivity();
获取NPE
的解决方案是:
使用 FragmentStatePagerAdapter
作为您的 ViewPager
的适配器。
并覆盖保存的状态方法:
@Override
public Parcelable saveState() {
return null;
}
我不知道为什么,但是 setRetainInstance(false);
对我没有帮助,我认为这对我来说仍然是个谜。
关于来自 viewpager getActivity 的 Android childfragments 返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26671390/