android常用框架源码解析,android Fragmentation框架源码全面解析一

Fragmentaion框架是一个很优秀的框架,我们有2个项目都使用过,目前无不良反应,BUG呢还是有一些,不过不妨碍它的优秀。

项目地址:https://github.com/YoKeyword/Fragmentation    点击打开链接

0818b9ca8b590ca3270a3433284dd417.png

关注好几千,群众的眼光是雪亮的。

它有啥作用呢?

Fragment是可以让你的app纵享丝滑的设计,如果你的app想在现在基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fragment要多,响应速度Fragment比Activty在中低端手机上快了很多,甚至能达到好几倍!如果你的app当前或以后有移植平板等平台时,可以让你节省大量时间和精力。

为"单Activity + 多Fragment的架构", "多模块Activity + 多Fragment的架构"而生,帮你简化使用过程,轻松解决各种复杂嵌套等问题,修复了官方Fragment库存在的一些BUG。

这句话是作者原话,意思就是说不用这个框架也可以实现它的效果,由于这个框架都封装好了我们想用的方法,可以让代码更简单,使用的感受呢就是纵享丝滑。

想详细了解,可以看看作者的全面解析博客

http://www.jianshu.com/p/d9143a92ad94    点击打开链接

下面开始进入正文

很久没更新这个框架了,我看了下,最新的和老版本核心代码都一样的,所以就用我这个版本分析吧

0818b9ca8b590ca3270a3433284dd417.png

导入源码可以看到总共分为4个部分,最外层有SupportActivity、SupportFraggment 等,里面有3个部分:anim、debug、

helper。

最外层的SupportActivity、SupportFragment是我们需要直接继承的基类,

animi 用于SupportFragment 直接的转场动画,

debug 顾名思义用于帮助查找框架中的bug,

helper 一些辅助类。

下面我们看下ISupport,

interfaceISupport {

/*** 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment**@paramcontainerId容器id*@paramtoFragment目标Fragment*/voidloadRootFragment(intcontainerId,SupportFragment toFragment);/*** 以replace方式加载根Fragment*/voidreplaceLoadRootFragment(intcontainerId,SupportFragment toFragment, booleanaddToBack);/*** 加载多个根Fragment**@paramcontainerId容器id*@paramtoFragments目标Fragments*/voidloadMultipleRootFragment(intcontainerId, intshowPosition,SupportFragment... toFragments);

一个定义了各种以后会直接使用到的常用方法,

ISupportFragment,继承ISupport的一个接口

interfaceISupportFragment extendsISupport {

/*** replace目标Fragment, 主要用于Fragment之间的replace**@paramtoFragment目标Fragment*@paramaddToBack是否添加到回退栈*/voidreplaceFragment(SupportFragment toFragment, booleanaddToBack);/***@return位于栈顶的子Fragment*/SupportFragment getTopChildFragment();/***@return当前Fragment的前一个Fragment*/SupportFragment getPreFragment();

在ISupport的基础上又定义了一些方法,因为定义的这些方法是在实现它的SupportFragment 中使用的。

public classSupportFragment extendsFragment implementsISupportFragment {

// LaunchModepublic static final intSTANDARD= 0;public static final intSINGLETOP= 1;public static final intSINGLETASK= 2;

而SupportActivity是直接实现ISupport的

public classSupportActivity extendsAppCompatActivity implementsISupport,SensorEventListener {

privateFragmentationDelegate mFragmentationDelegate;privateLifecycleHelper mLifecycleHelper;privateArrayList mFragmentLifecycleCallbacks;privateFragmentAnimator mFragmentAnimator;

ISupport及ISupportFragment里面定义的方法就是我们以后需要直接使用的主要方法了,

先来看下SupportActivity,

@Overrideprotected voidonCreate(@NullableBundle savedInstanceState) {

super.onCreate(savedInstanceState);mFragmentationDelegate= getFragmentationDelegate();mFragmentAnimator= onCreateFragmentAnimator();}

初始化中创建了FragmentationDelegate对象和转场动画对象,FragmentationDelegate是干嘛的呢?

0818b9ca8b590ca3270a3433284dd417.png

SupportFragment和SupportActivity中核心方法都会用到FragmentaionDelegate,

说白了整个框架的核心业务都在FragmentaionDelegate里面,主要包含了这些事务:

加载根Fragment、加载多个根Fragment、替换根Fragment、子Fragment之间的替换、隐藏显示Fragment、启动目标Fragment、

得到位于栈顶Fragment、获取栈内的Fragment、Fragment出栈、出栈到目标fragment、获取栈顶的子Fragment、

获取当前Fragment的前一个Fragment、子栈内Fragment出栈

现在开始一个一个方法突破吧!

一、加载根Fragment

voidloadRootTransaction(FragmentManager fragmentManager, intcontainerId,ISupportFragment to, booleanaddToBackStack, booleanallowAnimation) {

fragmentManager = checkFragmentManager(fragmentManager, null);if(fragmentManager == null) return;bindContainerId(containerId,to);start(fragmentManager, null,to,to.getClass().getName(),!addToBackStack, null,allowAnimation,TYPE_REPLACE);}

首先检查了下fragmentManager存不存在,不存在就没后面的,所以一般情况下是存在的,

private voidbindContainerId(intcontainerId,ISupportFragment to) {

Bundle args = getArguments((Fragment) to);args.putInt(FRAGMENTATION_ARG_CONTAINER,containerId);}

bindContainerId() 把视图容器id存在目标Fragment的Arguments中,

private voidstart(FragmentManager fragmentManager, finalISupportFragment from,ISupportFragment to,String toFragmentTag,booleandontAddToBackStack,ArrayList sharedElementList, booleanallowRootFragmentAnim, inttype) {

FragmentTransaction ft = fragmentManager.beginTransaction();booleanaddMode = (type == TYPE_ADD|| type == TYPE_ADD_RESULT|| type == TYPE_ADD_WITHOUT_HIDE);Fragment fromF = (Fragment) from;Fragment toF = (Fragment) to;Bundle args = getArguments(toF);args.putBoolean(FRAGMENTATION_ARG_REPLACE,!addMode);if(sharedElementList == null) {

if(addMode) { // Replace mode forbidden animation, the replace animations exist overlapping Bug on support-v4.TransactionRecord record = to.getSupportDelegate().mTransactionRecord;if(record != null&& record.targetFragmentEnter!= Integer.MIN_VALUE) {

ft.setCustomAnimations(record.targetFragmentEnter,record.currentFragmentPopExit,record.currentFragmentPopEnter,record.targetFragmentExit);args.putInt(FRAGMENTATION_ARG_CUSTOM_END_ANIM,record.targetFragmentEnter);} else{

ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);}

} else{

args.putInt(FRAGMENTATION_ARG_ROOT_STATUS,SupportFragmentDelegate.STATUS_ROOT_ANIM_DISABLE);}

} else{

args.putBoolean(FRAGMENTATION_ARG_IS_SHARED_ELEMENT, true);for(TransactionRecord.SharedElement item : sharedElementList) {

ft.addSharedElement(item.sharedElement,item.sharedName);}

}

if(from == null) {

ft.replace(args.getInt(FRAGMENTATION_ARG_CONTAINER),toF,toFragmentTag);if(!addMode) {

ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);args.putInt(FRAGMENTATION_ARG_ROOT_STATUS,allowRootFragmentAnim ?

SupportFragmentDelegate.STATUS_ROOT_ANIM_ENABLE: SupportFragmentDelegate.STATUS_ROOT_ANIM_DISABLE);}

} else{

if(addMode) {

ft.add(from.getSupportDelegate().mContainerId,toF,toFragmentTag);if(type != TYPE_ADD_WITHOUT_HIDE) {

ft.hide(fromF);}

} else{

ft.replace(from.getSupportDelegate().mContainerId,toF,toFragmentTag);}

}

if(!dontAddToBackStack && type != TYPE_REPLACE_DONT_BACK) {

ft.addToBackStack(toFragmentTag);}

supportCommit(fragmentManager,ft);}

接下来这个start()就稍微复杂些了,主要业务都在里面,也是一个很公用的方法,包含了fragment的添加、替换,

参数也比较多,

FragmentManager fragmentManager:Fragment管理器

ISupportFragment from:当前Fragment

ISupportFragment to: 目标Fragment,即需要开启的Fragment,方式可能是add或replace

String toFragmentTag:目标Fragment的tag,通过这个tag可以从栈中找到它

boolean dontAddToBackStack:是否不允许添加入栈,感觉有点别扭,直接名字叫是否允许入栈多好

ArrayList sharedElementList:过渡元素,过渡动画时用

boolean allowRootFragmentAnim:是否允许根Fragment动画

int type:添加Fragment的类型

这个方法主要分为3块,

第一块,判断有无过渡动画元素,添加相应的动画

第二块,当前fragment是否为空,然后做出add或replace fragment

第三块,是否允许把目标fragment添加入栈

然后提交事务。

二、加载多个根Fragment

voidloadMultipleRootTransaction(FragmentManager fragmentManager, intcontainerId, intshowPosition,ISupportFragment... tos) {

fragmentManager = checkFragmentManager(fragmentManager, null);if(fragmentManager == null) return;FragmentTransaction ft = fragmentManager.beginTransaction();for(inti = 0;i < tos.length;i++) {

Fragment to = (Fragment) tos[i];Bundle args = getArguments(to);args.putInt(FRAGMENTATION_ARG_ROOT_STATUS,SupportFragmentDelegate.STATUS_ROOT_ANIM_DISABLE);bindContainerId(containerId,tos[i]);String toName = to.getClass().getName();ft.add(containerId,to,toName);if(i != showPosition) {

ft.hide(to);}

}

supportCommit(fragmentManager,ft);}

这个方法比start()逻辑少点,因为这个方法没它公用的地方多,整个方法主要就要一个for循环,然后一个一个的添加,显示指定位置的Fragment,其他添加的都隐藏。

三、启动一个Fragment

public voidstart(ISupportFragment toFragment) {

start(toFragment,ISupportFragment.STANDARD);}

/***@paramlaunchModeSimilar to Activity's LaunchMode.*/public voidstart(finalISupportFragment toFragment,@ISupportFragment.LaunchModeintlaunchMode) {

mTransactionDelegate.dispatchStartTransaction(mFragment.getFragmentManager(),mSupportF,toFragment,0,launchMode,TransactionDelegate.TYPE_ADD);}

voiddispatchStartTransaction(FragmentManager fragmentManager,ISupportFragment from,ISupportFragment to, intrequestCode, intlaunchMode, inttype) {

fragmentManager = checkFragmentManager(fragmentManager,from);if(fragmentManager == null) return;checkNotNull(to,"toFragment == null");if(from != null) {

if(from.getSupportDelegate().mContainerId== 0) {

Fragment fromF = (Fragment) from;if(fromF.getTag() != null&& !fromF.getTag().startsWith("android:switcher:")) {

throw newRuntimeException("Can't find container, please call loadRootFragment() first!");}

}

bindContainerId(from.getSupportDelegate().mContainerId,to);from = SupportHelper.getTopFragment(fragmentManager,from.getSupportDelegate().mContainerId);}

// process SupportTransactionString toFragmentTag = to.getClass().getName();booleandontAddToBackStack = false;ArrayList sharedElementList = null;TransactionRecord transactionRecord = to.getSupportDelegate().mTransactionRecord;if(transactionRecord != null) {

if(transactionRecord.tag!= null) {

toFragmentTag = transactionRecord.tag;}

dontAddToBackStack = transactionRecord.dontAddToBackStack;if(transactionRecord.sharedElementList!= null) {

sharedElementList = transactionRecord.sharedElementList;// Compat SharedElementFragmentationHack.reorderIndices(fragmentManager);}

}

if(type == TYPE_ADD_RESULT|| type == TYPE_ADD_RESULT_WITHOUT_HIDE) {

saveRequestCode((Fragment) to,requestCode);}

if(handleLaunchMode(fragmentManager,from,to,toFragmentTag,launchMode)) return;if(type == TYPE_ADD_WITH_POP) {

startWithPop(fragmentManager,from,to);} else{

start(fragmentManager,from,to,toFragmentTag,dontAddToBackStack,sharedElementList, false,type);}

}

这也是非常核心的一个方法,将会是用得最多的方法,

如果fromFragment为空的则用加载根Fragment的方式开启,不为空就把视图容器id传给目标fragment,

接下来取出目标Fragment中的过渡动画相关的参数,然后如果添加类型为带requestCode,就调用

saveRequestCode((Fragment) to, requestCode)把这个requestCode保存起来,

if(handleLaunchMode(fragmentManager,from,to,toFragmentTag,launchMode)) return;

如果启动模式为SINGLETOP 或 SINGLETASK,就return掉,跟Activity的启动模式一样,

接下来根据条件复用startWithPop()或start()

未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值