Android深入FragmentStateAdapter
FragmentPagerAdapter与FragmentStateAdapter的区别
使用FragmentPagerAdapter 时,Fragment对象会一直存留在内存中,所以数据不能过多,FragmentPagerAdapter 适用于只有数量少的页面,例如选项卡。
FragmentStatePagerAdapter
当页面数据很多的时候就可以考虑使用FragmentStatePagerAdapte
源码简单解读
onCreateViewHolder()方法
public final FragmentViewHolder onCreateViewHolder (@NonNull ViewGroup parent,int viewType){
return FragmentViewHolder.create(parent);
}
static FragmentViewHolder create (ViewGroup parent){
FrameLayout container = new FrameLayout(parent.getContext());
container.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
container.setId(ViewCompat.generateViewId());
container.setSaveEnabled(false);
return new FragmentViewHolder(container);
}
onCreateViewHolder()创建一个宽高都 MATCH_PARENT 的 FrameLayout,注意这 里并不像 PagerAdapter 是 Fragment 的 rootView;
onBindViewHolder()
public final void onBindViewHolder(final @NonNull FragmentViewHolder holder, int position) {
final long itemId = holder.getItemId();
final int viewHolderId = holder.getContainer().getId();
final Long boundItemId = itemForViewHolder(viewHolderId); // item currently bound to the VH
if (boundItemId != null && boundItemId != itemId) {
removeFragment(boundItemId);
525 mItemIdToViewHolder.remove(boundItemId);
} mItemIdToViewHolder.put(itemId, viewHolderId);
// 这可能会覆盖现有条目
// 保证目标 Fragment 不为空,意思是可以提前创建 ensureFragment(position);
/** Special case when {@link RecyclerView} decides to keep the {@link container} *
attached to the window, but not to the view hierarchy (i.e. parent is null) */
final FrameLayout container = holder.getContainer();
// 如果 ItemView 已经在添加到 Window 中,且 parent 不等于 null,会触发绑定 viewHoder 操作;
if (ViewCompat.isAttachedToWindow(container)) {
if (container.getParent() != null) {
throw new IllegalStateException("Design assumption violated.");
}
container.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (container.getParent() != null) {
container.removeOnLayoutChangeListener(this); //将 Fragment 和 ViewHolder 绑定
placeFragmentInViewHolder(holder);
}
}
});
}
//回收垃圾
Fragments gcFragments();
}
onBindViewHolder()首先会获取当前 position 对应的 Fragment,这意味着预加载的 Fragment 对象会提前创建;
如果当前的 holder.itemView
已经添加到屏幕且已经布局且 parent 不等于空,就会将Fragment 绑定到ViewHodler;
每次调用都会 gc 一次,主要的避免用户修改数据源造成垃圾对象;
onViewAttachedToWindow()
public final void onViewAttachedToWindow (
@NonNull final FragmentViewHolder holder){
placeFragmentInViewHolder(holder);
gcFragments();
}
onViewAttachedToWindow()方法调用 onViewAttachedToWindow
将Fragment和hodler绑定
onViewRecycled()
public final void onViewRecycled (@NonNull FragmentViewHolder holder){
final int viewHolderId = holder.getContainer().getId();
final Long boundItemId = itemForViewHolder(viewHolderId);
// 当前绑定到VH的项目
if (boundItemId != null) {
removeFragment(boundItemId);
mItemIdToViewHolder.remove(boundItemId);
}
}
当 onViewRecycled()时才会触发 Fragment 移除
Fragment懒加载
懒加载效果
setoffscreenPageLimit(0);
Fragment 中监听不到 setUserVisibleHint
在设置 offscreenPageLimit>0
时,Fragment 中是监听不到 setUserVisibleHint
调用的,源码里面没有调用,而且该方法被标记过时,所以,适用于 ViewPager
那一套懒加载 Fragment 在这里是不行的;
在遇到 offscreenPageLimit>0
时,处理离屏 Fragment
和
可见 Fragment 没有什么区别,所以无法通过 setUserVisibleHint 判断显示与否,这一点知得注意.
转载自:https://juejin.cn/post/7036344431875719182