在Android开发中,FragmentTransaction 是用来管理 Fragment 的添加、移除、替换、显示和隐藏的主要工具。接下来我们会解释如何封装一个方法来实现多个 Fragment 的切换,并且分析每种操作(add, replace, show, hide)对 Fragment 生命周期的影响。
封装多个 Fragment 切换的方法
我们需要一个方法来切换两个 Fragment,我们可以创建一个辅助类或者方法来处理这些事务。将多个Fragment切换封装传入FragmentTransaction、Fragment、tag:
public void switchFragment(FragmentTransaction fragmentTransaction, Fragment newFragment, String tag) {
if (newFragment != null) {
// 如果Fragment已经在FragmentManager中存在,则先从back stack中移除它
if (newFragment.isAdded()) {
fragmentTransaction.show(newFragment);
} else {
fragmentTransaction.add(R.id.fragment_container, newFragment, tag);
}
}
fragmentTransaction.commit();
}
这个方法接受一个 FragmentTransaction 对象,一个新的 Fragment 和一个 tag。如果新的 Fragment 已经被添加到 FragmentManager 中,那么就显示它;否则,就将它添加到指定的容器中。
可以进一步封装,只需要传入对应的tag,同时允许传入参数Bundle
public void replaceFragment(String tag, Bundle bundle) {
Fragment tempFragment = getSupportFragmentManager().findFragmentByTag(tag);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (tempFragment == null) {
try {
//tempFragment = (Fragment) Class.forName(tag).newInstance();
tempFragment = (Fragment) Class.forName(tag).getDeclaredConstructor().newInstance();//无参数的构造方法
if (bundle!=null) {
tempFragment.setArguments(bundle);
}
transaction.add(R.id.fragment, tempFragment, tag);
this.curFragment = (BaseFragment) tempFragment;
} catch (Exception e) {
e.printStackTrace();
}
}
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (int i = 0; i < fragments.size(); i++) {
Fragment fragment = fragments.get(i);
if (fragment.getTag().equals(tag)) {
if (bundle!=null) {
fragment.setArguments(bundle);
}
transaction.show(fragment);
this.curFragment = (BaseFragment) fragment;
} else {
transaction.hide(fragment);
}
}
}
transaction.commitAllowingStateLoss();
}
完善上述封装,增加调试信息,方便查阅
private void replaceFragment(String tag, Bundle bundle) {
// 获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
// 检查FragmentManager是否存在
if (fragmentManager == null) {
Log.e("TAG", "FragmentManager is null");
return;
}
// 查找已存在的Fragment
Fragment tempFragment = fragmentManager.findFragmentByTag(tag);
// 开始事务
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 如果Fragment不存在,创建一个新的Fragment
if (tempFragment == null) {
try {
Class<?> clazz = Class.forName(tag);
tempFragment = (Fragment) clazz.getDeclaredConstructor().newInstance();
// 设置Bundle参数
tempFragment.setArguments(bundle);
// 添加Fragment到容器
transaction.add(R.id.fragment, tempFragment, tag);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
Log.e("TAG", "Error creating fragment", e);
return;
}
} else {
// 如果Fragment存在,更新其参数
tempFragment.setArguments(bundle);
}
// 遍历所有Fragment,只显示目标Fragment,隐藏其他Fragment
List<Fragment> fragments = fragmentManager.getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null && fragment.getTag().equals(tag)) {
// 显示目标Fragment
transaction.show(fragment);
this.curFragment = (BaseFragment) fragment;
} else if (fragment != null) {
// 隐藏其他Fragment
transaction.hide(fragment);
}
}
}
// 提交事务
transaction.commitAllowingStateLoss();
}
Fragment 生命周期的影响
当使用 FragmentTransaction 的不同方法时,它们会影响 Fragment 的生命周期方法的调用。下面是每种方法对 Fragment 生命周期的影响:
-
add: 当添加一个新的
Fragment到活动中时,它的生命周期会经历从onAttach()到onResume()的所有阶段,前提是这个Fragment在添加后是可见的。 -
replace:
replace方法与add类似,但它会移除容器中现有的Fragment并添加新的Fragment。对于新Fragment,它的生命周期也是从onAttach()到onResume()。而对于被替换的Fragment,它的生命周期将会经历从onPause()到onDetach()。 -
show: 当展示一个已经添加但被隐藏的
Fragment时,它的生命周期不会从头开始执行,只会从onHiddenChanged(false)开始,如果它之前是不可见的话。这意味着如果Fragment之前是暂停状态(paused),那么它将保持暂停状态直到活动恢复。 -
hide: 隐藏一个
Fragment会触发onHiddenChanged(true),但是其他生命周期方法如onPause()或onStop()不会被调用。隐藏的Fragment仍然存在于活动中并且可能会接收一些事件。
commit、commitAllowingStateLoss和executePendingTransactions区别
- 使用
commit()方法提交FragmentTransaction时,需要确保不是在onCreate(),onCreateView()或者onActivityCreated()方法中进行,因为这可能导致内存泄漏或其他问题。 - 在
commit()后,如果需要等待事务完成,可以使用commitAllowingStateLoss()或者通过FragmentManager的executePendingTransactions()方法。 - 如果需要做更复杂的事务,例如回退堆栈的操作,可能需要使用
addToBackStack(String)方法来管理事务的历史记录。 - 应用需要支持API Level 17(Android 4.2)及以下版本,建议使用
commit()而不是commitAllowingStateLoss(),因为后者允许在FragmentManager的状态丢失的情况下提交事务,这可能导致用户界面的意外行为。然而,对于现代Android应用,通常推荐使用commitAllowingStateLoss(),因为它提供了更好的用户体验。
当前文章价值0.36元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

评论已关闭!