前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >androidx下的fragment的lazy懒加载问题详解

androidx下的fragment的lazy懒加载问题详解

作者头像
砸漏
发布2020-10-20 15:39:12
2K0
发布2020-10-20 15:39:12
举报
文章被收录于专栏:恩蓝脚本

网上关于androidx的fragment懒加载文章已经有很多,各有侧重。几乎都点到了sexMaxLifecycle和修改FragmentPagerAdapter。很少看到经过实践的文章,谨以此文,更加详尽的把实践后的结果记录下来,赠予有缘人。

一、前置准备工作

几个关于androidx的fragment懒加载方案,都离不开如下几个包:

  • androidx.fragment:fragment:1.1.0-alpha07 以上,支持setMaxLifecycle方法即可
  • androidx.viewpager:viewpager:1.0.0 以上,如果涉及到viewpager内的fragment使用

我在实际测试代码中使用了如下版本,可供参考:

  • androidx.fragment:fragment:1.2.4
  • androidx.viewpager:viewpager:1.0.0
  • FlycoTabLayout

还准备了4个Activity与5个Fragment:

  • AddShowHideFragmentActivity 通过add show显示的案例
  • AddShowHideFragmentInFragmentActivity 嵌套在fragment中的,通过add show显示的fragment案例
  • ViewPagerFragmentActivity 通过ViewPager滑动显示的案例
  • ViewPagerFragmentInFragmentActivity 嵌套在fragment中的,通过ViewPager滑动显示的案例
  • AddFragmentInFragment 操作add show的fragment
  • ViewPagerFragmentInFragment 操作ViewPager的fragment
  • BlankFragment1 打印生命周期日志的空页面1
  • BlankFragment2 打印生命周期日志的空页面2
  • BlankFragment3 打印生命周期日志的空页面3

相应的几个简单布局文件:

文件:fragment_main.xml

加载ViewPager控件和AddShow使用的FrameLayout,以及测试跳转后返回的TextView按钮。

fragment_main.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"? 
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
   

  <androidx.viewpager.widget.ViewPager
    android:id="@+id/vp_fragment"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    / 

  <com.flyco.tablayout.CommonTabLayout
    android:id="@+id/tab_title"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@color/colorPrimary"
    app:tl_indicator_color="@color/colorAccent"
    app:tl_indicator_height="2dp"
    app:tl_indicator_width="30dp"
    app:tl_tab_space_equal="true"
    app:tl_textBold="SELECT"
    app:tl_textSelectColor="#000000"
    app:tl_textUnselectColor="#333333"
    app:layout_constraintTop_toBottomOf="@id/vp_fragment"
    app:layout_constraintLeft_toLeftOf="parent"
    / 

  <FrameLayout
    android:id="@+id/fl_in_content"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:layout_constraintTop_toBottomOf="@id/tab_title"
    / 

  <TextView
    android:id="@+id/tv_next"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:text="next"
    android:gravity="center"
    app:layout_constraintBottom_toBottomOf="parent"
    / 

</androidx.constraintlayout.widget.ConstraintLayout 

文件:activity_lazy_fragment.xml

这里是测试fragment嵌套情况下的布局,fl_content用来加载fragment

activity_lazy_fragment.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"? 
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".lazyFragment.ViewPagerFragmentActivity" 

  <FrameLayout
    android:id="@+id/fl_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    / 

</androidx.constraintlayout.widget.ConstraintLayout 

文件:fragment_blank.xml

这一个空fragment就没什么讲究了

fragment_blank.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"? 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
   

  <TextView
    android:id="@+id/tv_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="" / 

</FrameLayout 

二、具体代码分析

1) ViewPager+Fragment

最常见的使用方式,由ViewPager滑动显示多个Fragment,直接上代码:

activity页面代码

其中就是个简单的viewpager设置adapter然后加载fragment集合显示

代码语言:javascript
复制
/**
 * viewpager内的fragment懒加载
 */
public class ViewPagerFragmentActivity extends BindActivity implements BlankFragment1.OnFragmentInteractionListener , BlankFragment2.OnFragmentInteractionListener, BlankFragment3.OnFragmentInteractionListener {

  private static final String KEY_FRAGMENT_1 = "1";
  private static final String KEY_FRAGMENT_2 = "2";
  private static final String KEY_FRAGMENT_3 = "3";
  @BindView(R.id.vp_fragment)
  ViewPager vp;
  @BindView(R.id.tv_next)
  TextView tv_next;
  BlankFragment1 blankFragment1;
  BlankFragment2 blankFragment2;
  BlankFragment3 blankFragment3;
  List<Fragment  fragmentList;
  @Override
  protected int setLayoutID() {
    return R.layout.fragment_main;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {

    tv_next.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Intent intent=new Intent(mContext, MMKVActivity.class);
        startActivity(intent);
      }
    });

    if(savedInstanceState != null){
      blankFragment1 = (BlankFragment1)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
      blankFragment2 = (BlankFragment2)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
      blankFragment3 = (BlankFragment3)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
    }

    fragmentList=new ArrayList< ();
    if (blankFragment1==null){
      fragmentList.add(blankFragment1=BlankFragment1.newInstance("11111",""));
    }else {
      fragmentList.add(blankFragment1);
    }
    if (blankFragment2==null){
      fragmentList.add(blankFragment2=BlankFragment2.newInstance("22222",""));
    }else {
      fragmentList.add(blankFragment2);
    }
    if (blankFragment3==null){
      fragmentList.add(blankFragment3=BlankFragment3.newInstance("333333",""));
    }else {
      fragmentList.add(blankFragment3);
    }

    vp.setAdapter(new BaseFragmentXPagerAdapter(getSupportFragmentManager(),fragmentList,null));

  }

  @Override
  public void onFragmentInteraction(Uri uri) {
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    if(blankFragment1 != null&&blankFragment1.isAdded()) {
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
    }
    if(blankFragment2 != null&&blankFragment2.isAdded()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
    }
    if(blankFragment3 != null&&blankFragment3.isAdded()){
      getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
    }
    super.onSaveInstanceState(outState);
  }
}

BaseFragmentXPagerAdapter页面代码

新版FragmentPagerAdapter多了2个常量

代码语言:javascript
复制
@Retention(RetentionPolicy.SOURCE)
  @IntDef({BEHAVIOR_SET_USER_VISIBLE_HINT, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT})
  private @interface Behavior { }

用在了构造方法中

代码语言:javascript
复制
/**
   * Constructor for {@link FragmentPagerAdapter}.
   *
   * If {@link #BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT} is passed in, then only the current
   * Fragment is in the {@link Lifecycle.State#RESUMED} state. All other fragments are capped at
   * {@link Lifecycle.State#STARTED}. If {@link #BEHAVIOR_SET_USER_VISIBLE_HINT} is passed, all
   * fragments are in the {@link Lifecycle.State#RESUMED} state and there will be callbacks to
   * {@link Fragment#setUserVisibleHint(boolean)}.
   *
   * @param fm fragment manager that will interact with this adapter
   * @param behavior determines if only current fragments are in a resumed state
   */
  public FragmentPagerAdapter(@NonNull FragmentManager fm,
      @Behavior int behavior) {
    mFragmentManager = fm;
    mBehavior = behavior;
  }

我们只需要在构造adapter时,使用BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT这个常量就行

代码语言:javascript
复制
/**
 * support lazy init
 */
public class BaseFragmentXPagerAdapter extends FragmentPagerAdapter {

  private List<Fragment  mFragmentList = new ArrayList< ();
  private List<String  mFragmentTitleList = new ArrayList< ();

  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,List<Fragment  fragmentList,List<String  fragmentTitleList) {
    this(fm,fragmentList,fragmentTitleList,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
  }
  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,List<Fragment  fragmentList,List<String  fragmentTitleList, int behavior) {
    super(fm, behavior);
    if (fragmentList!=null){
      mFragmentList.addAll(fragmentList);
    }
    if (fragmentTitleList!=null){
      mFragmentTitleList.addAll(fragmentTitleList);
    }
  }

  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,Fragment[] fragmentList,String[] fragmentTitleList) {
    this(fm,fragmentList,fragmentTitleList,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
  }
  public BaseFragmentXPagerAdapter(@NonNull FragmentManager fm,Fragment[] fragmentList,String[] fragmentTitleList, int behavior) {
    super(fm, behavior);
    if (fragmentList!=null){
      for (int i = 0; i < fragmentList.length; i++) {
        mFragmentList.add(fragmentList[i]);
      }
    }
    if (fragmentTitleList!=null){
      for (int i = 0; i < fragmentTitleList.length; i++) {
        mFragmentTitleList.add(fragmentTitleList[i]);
      }
    }
  }

  @NonNull
  @Override
  public Fragment getItem(int position) {
    if (mFragmentList!=null&&!mFragmentList.isEmpty()){
      return mFragmentList.get(position);
    }else {
      return null;
    }
  }

  @Override
  public int getCount() {
    if (mFragmentList!=null&&!mFragmentList.isEmpty()){
      return mFragmentList.size();
    }else {
      return 0;
    }
  }

  @Nullable
  @Override
  public CharSequence getPageTitle(int position) {
    if (mFragmentTitleList!=null&&!mFragmentTitleList.isEmpty()&&position<mFragmentTitleList.size()){
      return mFragmentTitleList.get(position);
    }else {
      return null;
    }
  }
}

最终打印生命周期日志,确认结果,viewPager+fragment搭配pagerAdapter的behavior在各种情况下的日志,可以看出新版viewPager+pagerAdapter实测下来,Fragment的onResume生命周期只会在当前页显示时调用

首次进入 显示第一页 ViewPagerFragmentActivity— onCreate ViewPagerFragmentActivity— onStart ViewPagerFragmentActivity— onResume BlankFragment1— onAttach BlankFragment1— onCreate BlankFragment2— onAttach BlankFragment2— onCreate BlankFragment1— onViewCreated BlankFragment1— onActivityCreated BlankFragment1— onStart BlankFragment2— onViewCreated BlankFragment2— onActivityCreated BlankFragment2— onStart BlankFragment1— onResume <<=================== 当前页

滑动到第二页 BlankFragment3— onAttach BlankFragment3— onCreate BlankFragment3— onViewCreated BlankFragment3— onActivityCreated BlankFragment3— onStart BlankFragment1— onPause BlankFragment2— onResume <<=================== 当前页

锁屏 BlankFragment2— onPause ViewPagerFragmentActivity— onPause BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentActivity— onStop ViewPagerFragmentActivity— onSaveInstanceState

解锁屏幕 ViewPagerFragmentActivity— onRestart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentActivity— onStart ViewPagerFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页

HOME回到桌面 BlankFragment2— onPause ViewPagerFragmentActivity— onPause BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentActivity— onStop ViewPagerFragmentActivity— onSaveInstanceState

返回app页面 ViewPagerFragmentActivity— onRestart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentActivity— onStart ViewPagerFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页

跳转新页面 BlankFragment2— onPause ViewPagerFragmentActivity— onPause MMKVActivity— onCreate MMKVActivity— onStart MMKVActivity— onResume BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentActivity— onStop ViewPagerFragmentActivity— onSaveInstanceState

返回ViewPager的页面 MMKVActivity— onPause ViewPagerFragmentActivity— onRestart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentActivity— onStart ViewPagerFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页 MMKVActivity— onStop MMKVActivity— onDestroy

2) Fragment嵌套Fragment内的ViewPager+Fragment

外层的activity只是add一个fragment

代码语言:javascript
复制
/**
 * fragment内的viewpager内的fragment懒加载
 */
public class ViewPagerFragmentInFragmentActivity extends BindActivity implements ViewPagerFragmentInFragment.OnFragmentInteractionListener ,BlankFragment1.OnFragmentInteractionListener, BlankFragment2.OnFragmentInteractionListener, BlankFragment3.OnFragmentInteractionListener {

  @Override
  protected int setLayoutID() {
    return R.layout.activity_lazy_fragment;
  }

  @Override
  protected void initViews(Bundle savedInstanceState) {
    FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
    transaction.add(R.id.fl_content, ViewPagerFragmentInFragment.newInstance("",""));
    transaction.commit();
  }

  @Override
  public void onFragmentInteraction(Uri uri) {

  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
  }
}

嵌套用的fragment类,ViewPagerFragmentInFragment

代码语言:javascript
复制
/**
* viewpager在一个fragment内
*/
public class ViewPagerFragmentInFragment extends BaseFragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private static final String KEY_FRAGMENT_1 = "1";
private static final String KEY_FRAGMENT_2 = "2";
private static final String KEY_FRAGMENT_3 = "3";
@BindView(R.id.vp_fragment)
ViewPager vp;
@BindView(R.id.tv_next)
TextView tv_next;
BlankFragment1 blankFragment1;
BlankFragment2 blankFragment2;
BlankFragment3 blankFragment3;
List<Fragment  fragmentList;
public ViewPagerFragmentInFragment() {
}
public static ViewPagerFragmentInFragment newInstance(String param1, String param2) {
ViewPagerFragmentInFragment fragment = new ViewPagerFragmentInFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
if(blankFragment1 != null&&blankFragment1.isAdded()) {
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
}
if(blankFragment2 != null&&blankFragment2.isAdded()){
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
}
if(blankFragment3 != null&&blankFragment3.isAdded()){
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
}
super.onSaveInstanceState(outState);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tv_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(mContext, MMKVActivity.class);
startActivity(intent);
}
});
if(savedInstanceState != null){
blankFragment1 = (BlankFragment1)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
blankFragment2 = (BlankFragment2)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
blankFragment3 = (BlankFragment3)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
}
fragmentList=new ArrayList< ();
if (blankFragment1==null){
fragmentList.add(blankFragment1=BlankFragment1.newInstance("11111",""));
}else {
fragmentList.add(blankFragment1);
}
if (blankFragment2==null){
fragmentList.add(blankFragment2=BlankFragment2.newInstance("22222",""));
}else {
fragmentList.add(blankFragment2);
}
if (blankFragment3==null){
fragmentList.add(blankFragment3=BlankFragment3.newInstance("333333",""));
}else {
fragmentList.add(blankFragment3);
}
vp.setAdapter(new BaseFragmentXPagerAdapter(mActivity.getSupportFragmentManager(),fragmentList,null));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}

实测日志可以发现,哪怕fragment是嵌套过的,Fragment的onResume生命周期也只会在当前页显示时调用:

首次进入显示第一页 ViewPagerFragmentInFragment— onStart ViewPagerFragmentInFragmentActivity— onStart ViewPagerFragmentInFragmentActivity— onResume ViewPagerFragmentInFragment— onResume BlankFragment1— onAttach BlankFragment1— onCreate BlankFragment2— onAttach BlankFragment2— onCreate BlankFragment1— onViewCreated BlankFragment1— onActivityCreated BlankFragment1— onStart BlankFragment2— onViewCreated BlankFragment2— onActivityCreated BlankFragment2— onStart BlankFragment1— onResume <<=================== 当前页

滑动到第二页 BlankFragment3— onAttach BlankFragment3— onCreate BlankFragment3— onViewCreated BlankFragment3— onActivityCreated BlankFragment3— onStart BlankFragment1— onPause BlankFragment2— onResume <<=================== 当前页

锁屏 ViewPagerFragmentInFragment— onPause BlankFragment2— onPause ViewPagerFragmentInFragmentActivity— onPause ViewPagerFragmentInFragment— onStop BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentInFragmentActivity— onStop ViewPagerFragmentInFragmentActivity— onSaveInstanceState

解锁屏幕 ViewPagerFragmentInFragmentActivity— onRestart ViewPagerFragmentInFragment— onStart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentInFragmentActivity— onStart ViewPagerFragmentInFragmentActivity— onResume ViewPagerFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页

HOME回到桌面 ViewPagerFragmentInFragment— onPause BlankFragment2— onPause ViewPagerFragmentInFragmentActivity— onPause ViewPagerFragmentInFragment— onStop BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentInFragmentActivity— onStop ViewPagerFragmentInFragmentActivity— onSaveInstanceState

返回app页面 ViewPagerFragmentInFragmentActivity— onRestart ViewPagerFragmentInFragment— onStart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentInFragmentActivity— onStart ViewPagerFragmentInFragmentActivity— onResume ViewPagerFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页

跳转新页面 ViewPagerFragmentInFragment— onPause BlankFragment2— onPause ViewPagerFragmentInFragmentActivity— onPause MMKVActivity— onCreate MMKVActivity— onStart MMKVActivity— onResume ViewPagerFragmentInFragment— onStop BlankFragment1— onStop BlankFragment2— onStop BlankFragment3— onStop ViewPagerFragmentInFragmentActivity— onStop ViewPagerFragmentInFragmentActivity— onSaveInstanceState

返回ViewPager的页面 MMKVActivity— onPause ViewPagerFragmentInFragmentActivity— onRestart ViewPagerFragmentInFragment— onStart BlankFragment1— onStart BlankFragment2— onStart BlankFragment3— onStart ViewPagerFragmentInFragmentActivity— onStart ViewPagerFragmentInFragmentActivity— onResume ViewPagerFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页

3) 通过add show hide操作多个fragment

activity代码中的一个细节为通过add show的页面,设置transaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED),让该fragment的生命周期能顺利走到resume;

通过hide隐藏的页面,设置transaction.setMaxLifecycle(fragmentList.get(i), Lifecycle.State.CREATED),使隐藏了的fragment生命周期只能走到创建阶段,无法走到resume方法。

代码语言:javascript
复制
/**
* add show hide下的fragment懒加载
*/
public class AddShowHideFragmentActivity extends BindActivity implements BlankFragment1.OnFragmentInteractionListener , BlankFragment2.OnFragmentInteractionListener, BlankFragment3.OnFragmentInteractionListener {
private static final String KEY_FRAGMENT_1 = "1";
private static final String KEY_FRAGMENT_2 = "2";
private static final String KEY_FRAGMENT_3 = "3";
@BindView(R.id.tab_title)
CommonTabLayout commonTabLayout;
@BindView(R.id.tv_next)
TextView tv_next;
BlankFragment1 blankFragment1;
BlankFragment2 blankFragment2;
BlankFragment3 blankFragment3;
List<Fragment  fragmentList;
@Override
protected int setLayoutID() {
return R.layout.fragment_main;
}
@Override
protected void initViews(Bundle savedInstanceState) {
tv_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(mContext, MMKVActivity.class);
startActivity(intent);
}
});
if(savedInstanceState != null){
blankFragment1 = (BlankFragment1)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
blankFragment2 = (BlankFragment2)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
blankFragment3 = (BlankFragment3)getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
}
fragmentList=new ArrayList< ();
if (blankFragment1==null){
fragmentList.add(blankFragment1=BlankFragment1.newInstance("11111",""));
}else {
fragmentList.add(blankFragment1);
}
if (blankFragment2==null){
fragmentList.add(blankFragment2=BlankFragment2.newInstance("22222",""));
}else {
fragmentList.add(blankFragment2);
}
if (blankFragment3==null){
fragmentList.add(blankFragment3=BlankFragment3.newInstance("33333",""));
}else {
fragmentList.add(blankFragment3);
}
ArrayList<CustomTabEntity  tabEntities = new ArrayList< ();
tabEntities.add(new TabLayoutEntity("商品1"));
tabEntities.add(new TabLayoutEntity("评价2"));
tabEntities.add(new TabLayoutEntity("详情3"));
commonTabLayout.setTabData(tabEntities);
commonTabLayout.setCurrentTab(0);
showFragment(fragmentList.get(0),false);
commonTabLayout.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelect(int position) {
showFragment(fragmentList.get(position),false);
}
@Override
public void onTabReselect(int position) {
showFragment(fragmentList.get(position),false);
}
});
}
private void showFragment(Fragment fragment,boolean replace){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (replace){
transaction.replace(R.id.fl_in_content,fragment);
}else {
if (!fragment.isAdded()){
transaction.add(R.id.fl_in_content,fragment,fragment.getClass().getSimpleName());
}
hideAllFragment(transaction,fragment);
transaction.show(fragment);
transaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED);
}
transaction.commit();
}
private void hideAllFragment(FragmentTransaction transaction,Fragment withoutFragment){
for (int i = 0; i < fragmentList.size(); i++) {
if (!fragmentList.get(i).equals(withoutFragment)&&fragmentList.get(i).isAdded()){
transaction.hide(fragmentList.get(i));
transaction.setMaxLifecycle(fragmentList.get(i), Lifecycle.State.CREATED);
}
}
}
@Override
public void onFragmentInteraction(Uri uri) {
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if(blankFragment1 != null&&blankFragment1.isAdded()) {
getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
}
if(blankFragment2 != null&&blankFragment2.isAdded()){
getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
}
if(blankFragment3 != null&&blankFragment3.isAdded()){
getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
}
super.onSaveInstanceState(outState);
}
}

首次进入 显示第一页 AddShowHideFragmentActivity— onCreate BlankFragment1— onAttach BlankFragment1— onCreate BlankFragment1— onViewCreated BlankFragment1— onActivityCreated BlankFragment1— onStart AddShowHideFragmentActivity— onStart AddShowHideFragmentActivity— onResume BlankFragment1— onResume <<=================== 当前页

点击显示第二页 BlankFragment2— onAttach BlankFragment2— onCreate BlankFragment1— onHiddenChanged=true BlankFragment1— onPause BlankFragment1— onStop BlankFragment1— onDestroyView BlankFragment2— onViewCreated BlankFragment2— onActivityCreated BlankFragment2— onStart BlankFragment2— onResume <<=================== 当前页

锁屏 lankFragment2— onPause AddShowHideFragmentActivity— onPause BlankFragment2— onStop AddShowHideFragmentActivity— onStop AddShowHideFragmentActivity— onSaveInstanceState

解锁屏幕 AddShowHideFragmentActivity— onRestart BlankFragment2— onStart AddShowHideFragmentActivity— onStart AddShowHideFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页

HOME回到桌面 BlankFragment2— onPause AddShowHideFragmentActivity— onPause BlankFragment2— onStop AddShowHideFragmentActivity— onStop AddShowHideFragmentActivity— onSaveInstanceState

返回app页面 AddShowHideFragmentActivity— onRestart BlankFragment2— onStart AddShowHideFragmentActivity— onStart AddShowHideFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页

跳转新页面 BlankFragment2— onPause AddShowHideFragmentActivity— onPause MMKVActivity— onCreate MMKVActivity— onStart MMKVActivity— onResume BlankFragment2— onStop AddShowHideFragmentActivity— onStop AddShowHideFragmentActivity— onSaveInstanceState

返回ViewPager的页面 MMKVActivity— onPause AddShowHideFragmentActivity— onRestart BlankFragment2— onStart AddShowHideFragmentActivity— onStart AddShowHideFragmentActivity— onResume BlankFragment2— onResume <<=================== 当前页

4) Fragment嵌套Fragment内的add show hide Fragment

外层的activity只是add一个fragment

代码语言:javascript
复制
/**
* fragment内的viewpager内的fragment懒加载
*/
public class AddShowHideFragmentInFragmentActivity extends BindActivity implements AddFragmentInFragment.OnFragmentInteractionListener ,BlankFragment1.OnFragmentInteractionListener, BlankFragment2.OnFragmentInteractionListener, BlankFragment3.OnFragmentInteractionListener {
@Override
protected int setLayoutID() {
return R.layout.activity_lazy_fragment;
}
@Override
protected void initViews(Bundle savedInstanceState) {
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fl_content,AddFragmentInFragment.newInstance("",""));
transaction.commit();
}
@Override
public void onFragmentInteraction(Uri uri) {
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
}

内部的fragment代码如下

代码语言:javascript
复制
/**
* add hide show显示的fragment 嵌套在 外层fragment内
*/
public class AddFragmentInFragment extends BaseFragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private static final String KEY_FRAGMENT_1 = "1";
private static final String KEY_FRAGMENT_2 = "2";
private static final String KEY_FRAGMENT_3 = "3";
@BindView(R.id.tab_title)
CommonTabLayout commonTabLayout;
@BindView(R.id.tv_next)
TextView tv_next;
BlankFragment1 blankFragment1;
BlankFragment2 blankFragment2;
BlankFragment3 blankFragment3;
List<Fragment  fragmentList;
public AddFragmentInFragment() {
}
public static AddFragmentInFragment newInstance(String param1, String param2) {
AddFragmentInFragment fragment = new AddFragmentInFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
if(blankFragment1 != null&&blankFragment1.isAdded()) {
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_1,blankFragment1);
}
if(blankFragment2 != null&&blankFragment2.isAdded()){
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_2,blankFragment2);
}
if(blankFragment3 != null&&blankFragment3.isAdded()){
mActivity.getSupportFragmentManager().putFragment(outState,KEY_FRAGMENT_3,blankFragment3);
}
super.onSaveInstanceState(outState);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tv_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(mContext, MMKVActivity.class);
startActivity(intent);
}
});
if(savedInstanceState != null){
blankFragment1 = (BlankFragment1)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_1);
blankFragment2 = (BlankFragment2)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_2);
blankFragment3 = (BlankFragment3)mActivity.getSupportFragmentManager().getFragment(savedInstanceState,KEY_FRAGMENT_3);
}
fragmentList=new ArrayList< ();
if (blankFragment1==null){
fragmentList.add(blankFragment1=BlankFragment1.newInstance("11111",""));
}else {
fragmentList.add(blankFragment1);
}
if (blankFragment2==null){
fragmentList.add(blankFragment2=BlankFragment2.newInstance("222222",""));
}else {
fragmentList.add(blankFragment2);
}
if (blankFragment3==null){
fragmentList.add(blankFragment3=BlankFragment3.newInstance("3333333",""));
}else {
fragmentList.add(blankFragment3);
}
ArrayList<CustomTabEntity  tabEntities = new ArrayList< ();
tabEntities.add(new TabLayoutEntity("商品1"));
tabEntities.add(new TabLayoutEntity("评价2"));
tabEntities.add(new TabLayoutEntity("详情3"));
commonTabLayout.setTabData(tabEntities);
commonTabLayout.setCurrentTab(0);
showFragment(fragmentList.get(0),false);
commonTabLayout.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelect(int position) {
showFragment(fragmentList.get(position),false);
}
@Override
public void onTabReselect(int position) {
showFragment(fragmentList.get(position),false);
}
});
}
private void showFragment(Fragment fragment,boolean replace){
FragmentTransaction transaction = mActivity.getSupportFragmentManager().beginTransaction();
if (replace){
transaction.replace(R.id.fl_in_content,fragment);
}else {
if (!fragment.isAdded()){
transaction.add(R.id.fl_in_content,fragment,fragment.getClass().getSimpleName());
}
hideAllFragment(transaction,fragment);
transaction.show(fragment);
transaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED);
}
transaction.commit();
}
private void hideAllFragment(FragmentTransaction transaction,Fragment withoutFragment){
for (int i = 0; i < fragmentList.size(); i++) {
if (!fragmentList.get(i).equals(withoutFragment)&&fragmentList.get(i).isAdded()){
transaction.hide(fragmentList.get(i));
transaction.setMaxLifecycle(fragmentList.get(i), Lifecycle.State.CREATED);
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}

实测日志可以发现,哪怕fragment是嵌套过的,Fragment的onResume生命周期也只会在当前页显示时调用:

首次进入 显示第一页 AddShowHideFragmentInFragmentActivity— onCreate AddFragmentInFragment— onAttach AddFragmentInFragment— onCreate AddFragmentInFragment— onViewCreated AddFragmentInFragment— onActivityCreated BlankFragment1— onAttach BlankFragment1— onCreate BlankFragment1— onViewCreated BlankFragment1— onActivityCreated AddFragmentInFragment— onStart BlankFragment1— onStart AddShowHideFragmentInFragmentActivity— onStart AddShowHideFragmentInFragmentActivity— onResume AddFragmentInFragment— onResume BlankFragment1— onResume <<=================== 当前页

点击显示第二页 BlankFragment2— onAttach BlankFragment2— onCreate BlankFragment1— onHiddenChanged=true BlankFragment1— onPause BlankFragment1— onStop BlankFragment1— onDestroyView BlankFragment2— onViewCreated BlankFragment2— onActivityCreated BlankFragment2— onStart BlankFragment2— onResume <<=================== 当前页

锁屏 AddFragmentInFragment— onPause BlankFragment2— onPause AddShowHideFragmentInFragmentActivity— onPause AddFragmentInFragment— onStop BlankFragment2— onStop AddShowHideFragmentInFragmentActivity— onStop AddShowHideFragmentInFragmentActivity— onSaveInstanceState

解锁屏幕 AddShowHideFragmentInFragmentActivity— onRestart AddFragmentInFragment— onStart BlankFragment2— onStart AddShowHideFragmentInFragmentActivity— onStart AddShowHideFragmentInFragmentActivity— onResume AddFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页 HOME回到桌面 AddFragmentInFragment— onPause BlankFragment2— onPause AddShowHideFragmentInFragmentActivity— onPause AddFragmentInFragment— onStop BlankFragment2— onStop AddShowHideFragmentInFragmentActivity— onStop AddShowHideFragmentInFragmentActivity— onSaveInstanceState

返回app页面 AddShowHideFragmentInFragmentActivity— onRestart AddFragmentInFragment— onStart BlankFragment2— onStart AddShowHideFragmentInFragmentActivity— onStart AddShowHideFragmentInFragmentActivity— onResume AddFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页

跳转新页面 AddFragmentInFragment— onPause BlankFragment2— onPause AddShowHideFragmentInFragmentActivity— onPause MMKVActivity— onCreate MMKVActivity— onStart MMKVActivity— onResume AddFragmentInFragment— onStop BlankFragment2— onStop AddShowHideFragmentInFragmentActivity— onStop AddShowHideFragmentInFragmentActivity— onSaveInstanceState

返回当前页 MMKVActivity— onPause AddShowHideFragmentInFragmentActivity— onRestart AddFragmentInFragment— onStart BlankFragment2— onStart AddShowHideFragmentInFragmentActivity— onStart AddShowHideFragmentInFragmentActivity— onResume AddFragmentInFragment— onResume BlankFragment2— onResume <<=================== 当前页

三、小结

上面列举了四种不同的使用场景,以及各种常见的操作逻辑,除了保证页面只有显示为当前页时才显示onResume生命周期函数外,也通过saveState方法解决了fragment销毁后,重叠显示的UI异常。

到此这篇关于androidx下的fragment的lazy懒加载问题详解的文章就介绍到这了,更多相关androidx fragment lazy懒加载内容请搜索ZaLou.Cn以前的文章或继续浏览下面的相关文章希望大家以后多多支持ZaLou.Cn!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,助力维护团队卓越代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档