ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ViewPager中使用Fragment时防止数据预加载,idea搭建android开发环境

2021-12-23 16:02:14  阅读:177  来源: 互联网

标签:false Fragment ViewPager idea fragment 源码 mCurrentPrimaryItem container


其中BaseFragment是我在项目中使用的一个基类就是继承了v4包中的Fragment,代码不贴了,你的项目中应该也会自己的基类,继承你自己的基类就好了。上面代码中主要在两个方法中进行了控制,onViewCreated()setUserVisibleHint, 另外这里我还使用了标志位,多重条件保证Fragment创建时数据不会被预加载且Fragment可见时只加载一次。

为什么这样可以在ViewPager中防止数据预加载呢,先来看一下setUserVisibleHint这个方法:

/**

  • Set a hint to the system about whether this fragment’s UI is currently visible

  • to the user. This hint defaults to true and is persistent across fragment instance

  • state save and restore.

  • An app may set this to false to indicate that the fragment's UI is

  • scrolled out of visibility or is otherwise not directly visible to the user.

  • This may be used by the system to prioritize operations such as fragment lifecycle updates

  • or loader ordering behavior.

  • Note: This method may be called outside of the fragment lifecycle.

  • and thus has no ordering guarantees with regard to fragment lifecycle method calls.

  • @param isVisibleToUser true if this fragment’s UI is currently visible to the user (default),

  •                    false if it is not.
    

*/

public void setUserVisibleHint(boolean isVisibleToUser) {

if (!mUserVisibleHint && isVisibleToUser && mState < STARTED

&& mFragmentManager != null && isAdded()) {

mFragmentManager.performPendingDeferredStart(this);

}

mUserVisibleHint = isVisibleToUser;

mDeferStart = mState < STARTED && !isVisibleToUser;

}

以上是来自support v4包中的Fragment源码, 大概的意思是调用这个方法来设置Fragment当前是否是对用户可见的,这个方法只有一个参数,visible就传true,否则就传false。可是在Fragment源码搜索发现并没有地方调用这个方法,那这个方法可能是给用户来调用的。

由此,我们可以猜想肯定是在ViewPager使用的过程中的某个地方调用了这个方法,我们看下ViewPager使用Fragment的流程一般是:

mAdapter = new BaseFragmentPagerAdapter(getSupportFragmentManager(), mFragmentList);

mViewPager.setAdapter(mAdapter);

于是,我先到FragmentPagerAdapter的源码中搜索了下,果不其然,发现了踪迹:

@SuppressWarnings(“ReferenceEquality”)

@Override

public Object instantiateItem(ViewGroup container, int position) {

if (mCurTransaction == null) {

mCurTransaction = mFragmentManager.beginTransaction();

}

final long itemId = getItemId(position);

// Do we already have this fragment?

String name = makeFragmentName(container.getId(), itemId);

Fragment fragment = mFragmentManager.findFragmentByTag(name);

if (fragment != null) {

if (DEBUG) Log.v(TAG, “Attaching item #” + itemId + “: f=” + fragment);

mCurTransaction.attach(fragment);

} el

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

se {

fragment = getItem(position);

if (DEBUG) Log.v(TAG, “Adding item #” + itemId + “: f=” + fragment);

mCurTransaction.add(container.getId(), fragment,

makeFragmentName(container.getId(), itemId));

}

if (fragment != mCurrentPrimaryItem) {

fragment.setMenuVisibility(false);

fragment.setUserVisibleHint(false);

}

return fragment;

}

在instantiateItem方法的最后我们发现了调用的地方:

if (fragment != mCurrentPrimaryItem) {

fragment.setMenuVisibility(false);

fragment.setUserVisibleHint(false);

}

这里有个判断fragment != mCurrentPrimaryItem这个时候会把Fragment的Visible设为false, 那这个mCurrentPrimaryItem又是什么呢,继续搜索源码:

@SuppressWarnings(“ReferenceEquality”)

@Override

public void setPrimaryItem(ViewGroup container, int position, Object object) {

Fragment fragment = (Fragment)object;

if (fragment != mCurrentPrimaryItem) {

if (mCurrentPrimaryItem != null) {

mCurrentPrimaryItem.setMenuVisibility(false);

mCurrentPrimaryItem.setUserVisibleHint(false);

}

if (fragment != null) {

fragment.setMenuVisibility(true);

fragment.setUserVisibleHint(true);

}

mCurrentPrimaryItem = fragment;

}

}

在一个setPrimaryItem的方法中找到这个变量的赋值,这个方法将传进来的fragment的visible设置为true, 同时会更新mCurrentPrimaryItem变量的值。我们再继续搜索setPrimaryItem这个方法的调用,结果在当前FragmentPagerAdapter的源码中没有找到,但是在它的父类PagerAdapter的源码中找到了它的定义:

/**

  • Called to inform the adapter of which item is currently considered to

  • be the “primary”, that is the one show to the user as the current page.

  • @param container The containing View from which the page will be removed.

  • @param position The page position that is now the primary.

  • @param object The same object that was returned by

  • {@link #instantiateItem(View, int)}.

*/

public void setPrimaryItem(ViewGroup container, int position, Object object) {

setPrimaryItem((View) container, position, object);

}

看注释大概明白了这个方法的含义是设置为ViewPager中当前展示给用户的那一页。

继续到ViewPager的源码中搜索,找到了调用它的地方:

这里写图片描述

是在一个populate()的方法中调用的,搜索发现好多地方调用了它,但是发现了有两个关键的地方:

/**

  • Set a PagerAdapter that will supply views for this pager as needed.

  • @param adapter Adapter to use

*/

public void setAdapter(PagerAdapter adapter) {

//…忽略部分源码

if (mAdapter != null) {

//…忽略部分源码

if (mRestoredCurItem >= 0) {

mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader);

setCurrentItemInternal(mRestoredCurItem, false, true);

mRestoredCurItem = -1;

mRestoredAdapterState = null;

mRestoredClassLoader = null;

} else if (!wasFirstLayout) {

populate();

} else {

requestLayout();

}

}

//…忽略部分源码

}

/**

  • Set the currently selected page.

  • @param item Item index to select

  • @param smoothScroll True to smoothly scroll to the new item, false to transition immediately

*/

public void setCurrentItem(int item, boolean smoothScroll) {

mPopulatePending = false;

setCurrentItemInternal(item, smoothScroll, false);

}

标签:false,Fragment,ViewPager,idea,fragment,源码,mCurrentPrimaryItem,container
来源: https://blog.csdn.net/m0_65512365/article/details/122109495

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有