前言
其实开发这些年,还是对Fragment了解比较偏少,这里就先整理下,如何系统掌握日常工作中Fragment的使用
Fragment优点
1、如果很多比较简单页面,而且前后是一整套跳转逻辑,使用多个Activity显得太笨重,如果单个Activity里面存在多个布局去显隐藏代码显得不易读懂,耦合性太强,那我们就可以采用Fragment,解决Activity间的切换不流畅,轻量切换。
2、Fragment其实是Acitivty中的一个控件而已,但是有一套完整的生命周期,这样我们可操作空间就显得很充裕。
Fragment使用
可参考文章Fragment早期完整使用解析
tips这篇系列文章其实很好的梳理了日常Fragment的使用,但是文章比较过老,所以我这边暂时是拿来当复习使用,后续还是得针对最新源码进行分析,这文章系列核心点我这边先暂时罗列一下,为日后做准备
1、注意Fragment的生命周期,以及在什么地方进行view的初始化,还有传参等事项。
2、注意生命周期方法跟用户的交互时间段
3、我们日常使用多是V4包中的Fragment,注意跟系统提供的Fragment的区别
4、FragmentManager的使用,主要是管理Activity中的Fragments
5、注意add、show尤其是跟replace的区别,这个直观感受是Fragment切换的时候,还有一点是注意add不能跟replace使用,这个是系统源码bug导致的,不知道新版有没有处理这些问题
6、了解下FragmentTrasncation的使用
7、了解Fragment中回退栈的概念,这个非常非常重要
8、Fragment在同一层布局上数据的传递,以及在上下层数据的传递,以及为啥使用setArgument进行数据的传递
9、replace是清空视图,如果重新显示是会重新绘制的,我们如何使用replace去回退的时候,依然保证用户输入后的状态,这个使用的还是回退栈的概念,是个非常核心的使用。
上续问题,在参考文章中都一一给予了解答,需要读者去认真了解
参考二 官网讲解
同层级Fragment切换的使用
项目中使用
package org.cy.uilibrary;
import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
/**
*
*/
public class FragmentUtils {
private static final String TAG = "FragmentUtils";
public static void replaceFragment(FragmentManager manager, Fragment fragment,
boolean addToBackStack) {
replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false,
R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
}
public static void showFragmentAllowingStateLoss(FragmentManager manager, Fragment fragment,
boolean addToBackStack) {
replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, true,
R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
}
public static void showFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack) {
replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false);
}
public static void showFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack, boolean commitStateLoss) {
replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, commitStateLoss);
}
public static void showFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack, int... animations) {
replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false, animations);
}
/**
* 每次返回执行生命周期
* @param manager fragment的事物管理者
* @param fragment 切换的fragment
* @param addToBackStack 是否加入回退栈
* @param resId fragment的 container
* @param animations fragment切换动画(请按照此顺序添加动画:enter->exit->popEnter->popExit)
*/
private static void replaceFragment(FragmentManager manager, Fragment fragment,
boolean addToBackStack, int resId, boolean commitStateLoss, int... animations) {
if (manager == null) {
return;
}
FragmentTransaction ft = manager.beginTransaction();
if (animations.length > 0) {
ft.setCustomAnimations(animations[0], animations[1], animations[2], animations[3]);
}
String fragmentName = fragment.getClass().getName();
Log.d("showFragment", "fragmentName = " + fragmentName);
ft.replace(resId, fragment, fragmentName);
if (addToBackStack) {
ft.addToBackStack(fragmentName);
}
try {
if (commitStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
} catch (Exception e) {
Log.e(TAG, "Exception:" + e.getMessage());
}
}
/***
* 不执行生命周期
* @param manager
* @param fragment
* @param addToBackStack
* @param resId
* @param commitStateLoss
* @param animations
*/
private static void addFragment(FragmentManager manager, Fragment fragment,
boolean addToBackStack, int resId, boolean commitStateLoss, int... animations) {
FragmentTransaction ft = manager.beginTransaction();
if (animations.length > 0) {
ft.setCustomAnimations(animations[0], animations[1], animations[2], animations[3]);
}
String fragmentName = fragment.getClass().getName();
ft.add(resId, fragment, fragmentName);
if (addToBackStack) {
ft.addToBackStack(fragmentName);
}
try {
if (commitStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
} catch (Exception e) {
Log.e(TAG, "Exception:" + e.getMessage());
}
}
public static void addFragment(FragmentManager manager, Fragment fragment,
boolean addToBackStack) {
addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false,
R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
}
public static void addFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack) {
addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false);
}
public static void addFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack, int... animations) {
addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false, animations);
}
public static void addFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
boolean addToBackStack, boolean commitStateLoss) {
addFragment(manager, fragment, addToBackStack, R.id.fragment_container, commitStateLoss);
}
public static Fragment getCurrentFragment(FragmentManager manager) {
return manager.findFragmentById(R.id.fragment_container);
}
public static String getCurrentFragmentTag(FragmentManager manager) {
int backStackEntryCount = manager.getBackStackEntryCount();
if (backStackEntryCount <= 0) {
return null;
}
String fragmentTag = manager.getBackStackEntryAt(
backStackEntryCount - 1).getName();
return fragmentTag;
}
/**
* 清除某个Fragment以及其以上的所有Fragment(这里需要注意的是会清除fragmentClass本身)
*
* @param fragmentClass 某个fragment class
*/
public static void clearFragment(FragmentManager manager, Class fragmentClass) {
int num = manager.getBackStackEntryCount();
for (int i = 0; i < num; i++) {
FragmentManager.BackStackEntry stackEntry = manager.getBackStackEntryAt(i);
if (stackEntry.getName().equals(fragmentClass.getName())) {
manager.popBackStack(stackEntry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
break;
}
}
}
/**
* 清除fragment栈除了最初的其他所有fragment
*/
public static void clearFragmentAll(FragmentManager manager) {
if (manager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
public static boolean containFragment(FragmentManager manager, Class fragmentClass) {
int num = manager.getBackStackEntryCount();
for (int i = 0; i < num; i++) {
FragmentManager.BackStackEntry stackEntry = manager.getBackStackEntryAt(i);
if (stackEntry.getName().equals(fragmentClass.getName())) {
return true;
}
}
return false;
}
public interface OnBackPressedListener {
boolean onBackPressed();
}
}
2、Fragment的源码分析
直接参考
fragmentX 源码硬核解析,强势推荐
add active类
fragment 5种通信