以前做法

  • 重写Fragment
package cool.hyz.xujiayi.base;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

/**
 * @author xujiayi
 * @date 2023/11/5
 * 我只是个自由的主!
 */
public abstract class BaseFragment extends Fragment {

    public static final String TAG = "BaseFragment";
    /**
     * 视图是否初始化
     */
    protected boolean isInit = false;
    protected boolean isLoad = false;


    private View mView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        //加载子view
        mView = onSubViewLoaded(inflater, container);

        isInit = true;
        //初始化的时候去加载数据
        isCanLoadData();
        return mView;
    }

    /**
     * 是否可以加载数据
     * 可以加载数据的条件:
     * 1.视图已经初始化
     * 2.视图对用户可见
     */
    private void isCanLoadData() {
        if (!isInit) return;
        Log.d(TAG, "isCanLoadData: "+getUserVisibleHint());
        if (getUserVisibleHint()&&!isLoad) {
            lazyLoadData();
            isLoad = true;
        } else {
            if (isLoad) stopLoadData();
        }
    }

    public abstract View createSuccess(LayoutInflater inflater, ViewGroup container);


    /**
     * 当视图初始化并且对用户可见的时候去真正的加载数据
     */
    protected abstract void lazyLoadData();

    /**
     * 当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以覆写此方法
     */
    protected void stopLoadData() {

    }

    protected abstract View onSubViewLoaded(LayoutInflater inflater, ViewGroup container);

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isInit = false;
        isLoad = false;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        isCanLoadData();
    }
}

java
  • 实现BaseFragment
package cool.hyz.xujiayi.views.home;

import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


import java.util.List;

import cool.hyz.xujiayi.R;
import cool.hyz.xujiayi.base.BaseFragment;

/**
 * @author xujiayi
 * @date 2023/11/5
 * 我只是个自由的主!
 */
public class HomeFragment extends BaseFragment {

    public static final String TAG = "HomeFragment";

    private Banner mBannerH;
    private Banner mBannerV;
    private View mRoot;

    public HomeFragment() {

    }

    @Override
    protected void lazyLoadData() {
        Log.d(TAG, "lazyLoadData: HomeView load data...");
    }

    @Override
    protected View onSubViewLoaded(LayoutInflater inflater, ViewGroup container) {
        mRoot = inflater.inflate(R.layout.fragment_home, container, false);
        return mRoot ;
    }

    @Override
    protected void stopLoad() {
        Log.d(TAG, "HomeFragment" + "已经对用户不可见,可以停止加载数据");
    }
}
java

问题

  • getUserVisibleHint() Deprecated;
  • setUserVisibleHint(boolean) Deprecated;

新做法

  • 使用FragmentPagerAdapter时直接使用两个参数的构造方法FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
package cool.hyz.xujiayi.adapters;

import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

import cool.hyz.xujiayi.creators.FragmentCreator;

public class FragPagerAdapter extends FragmentPagerAdapter {
    public FragPagerAdapter(@NonNull FragmentManager fm) {
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return FragmentCreator.getFragment(position);
    }

    @Override
    public int getCount() {
        return FragmentCreator.PAGE_COUNT;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        //切换时不销毁page
        //super.destroyItem(container, position, object);
    }

}
java

原理

  1. 通过FragmentTransactionsetMaxLifecycle()方法——替代setUserVisibleHint()方法实现Fragment的懒加载效果。
  2. instantiateItem()setMaxLifecycle()设置的Fragment状态为STARTED,即通过ViewPager.offscreenPageLimit设置提前初始化时,临近的Fragment最多执行到onStart()方法,不会再执行onResume()方法了
  3. 如果需要Fragment只执行一次对应逻辑且Fragment重新加载View时需要重置,之前通常会通过setUserVisibleHint(isVisibleToUser: Boolean)里通过isVisibleToUser以及自定义的isLoaded去判断,现在可以直接将逻辑写到onResume中:
...

public class HomeFragment extends BaseFragment {

    public static final String TAG = "HomeFragment";

    ...

    private boolean isLoaded = false;

    @Override
    public void onResume() {
        super.onResume();
        if(!isLoaded){
	    //TODO: 数据加载
	    ...

            isLoaded = true;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isLoaded = false;
    }
}
java

参考文章

  1. Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案
  2. Fragment.setUserVisibleHint()懒加载过时问题优化
打赏
  • 微信
  • 支付宝
评论
来发评论吧~
···

歌手: