Android ViewPager+Fragment(使用问题处理)

ViewPager+Fragment可以非常高效地实现动态编辑多个相似页面。

但是ViewPager会预加载Fragment(左右n(n>=1)个页面) ,导致Fragment的onResume()和onPause()可能不会按预期的执行。在接入友盟统计时,页面统计需要Activity和Fragment的onResume()和onPause()配对,但ViewPager中的Fragment会出现调用顺序问题。

无论如何,对于Fragment,我的期望是显示的时候执行onResume(),隐藏的时候执行onPause()

检测Fragment是否显示有2个方法:

  1. setUserVisibleHint(boolean isVisibleToUser)
  2. getUserVisibleHint()

 ViewPager中的Fragment本身做不到显示的时候执行onResume(),隐藏的时候执行onPause(),所以我要设置方法,让这个方法来做到这样的效果:

    /**
     * 替代具有不确定性的onResume()(ViewPager可能会让多个fragment执行onResume(),但有些fragment执行后是不可见状态的)
     * 我需要的是执行onResume后,确定是可见状态的方法
     */
    protected void onResumeVisible() {}

    /**
     * 替代具有不确定性的onPause()(ViewPager可能会让多个fragment执行onPause())
     * 我需要的是执行onPause前,确定执行onResume()
     */
    protected void onPauseInVisible() {}

 当然,优化Fragment基本考虑到懒加载,顺便实现。全部代码

/**
 * Copyright (C)
 * FileName: BaseFragment
 * Author: wudengwei
 * Date: 2018/12/17 20:15
 * Description: 解决ViewPager中使用显示与隐藏和onResume()与onPause()不一致问题
 */
public class BaseFragment extends Fragment {
    protected Activity mActivity;
    //是否第一次可见
    private boolean isFirstVisible = true;
    //是否可见
    private boolean isVisible = false;
    /**
     * onResume是否已经执行,fragment在ViewPager中
     * 第一次创建时(预加载)不管可不可见,都会执行一次生命周期
     * isFirstOnResume=false表示预加载或当前显示的fragment执行了onResume()
     * isFirstOnResume=false,fragment再次显示时,当做执行了onResume()
     */
    private boolean isFirstOnResume = true;

    /**
     * 作用于onResume()在显示状态下执行后,fragment隐藏时执行对应的onPause()
     * 避免其他页面的onPause()执行
     * 是否可以使用isVisible代替?
     */
    private boolean isOnResumeVisible = false;

    @Override
    public void onAttach(Context context) {
        this.mActivity = (Activity) context;
        super.onAttach(context);
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (getView() == null)
            return;
        /*可见回调方法*/
        if (isVisible != isVisibleToUser)
            onVisibleChange(isVisibleToUser,isFirstVisible);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        isFirstVisible = true;
        isVisible = false;
        isFirstOnResume = true;
        isOnResumeVisible = false;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (getUserVisibleHint()) {
            /*可见,是否第一次*/
            onVisibleChange(true,isFirstVisible);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (isFirstOnResume) {
            isFirstOnResume = false;
        }
        if (getUserVisibleHint() && !isOnResumeVisible) {//onResume()在可见状态下调用
            isOnResumeVisible = true;
            onResumeVisible();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        //onResume()在可见状态下调用后,进入onPause()
        if (!isFirstOnResume && isOnResumeVisible) {
            isOnResumeVisible = false;
            onPauseInVisible();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isFirstVisible = true;
        isVisible = false;
        isFirstOnResume = true;
    }

    /*是否可见回调方法*/
    protected void onVisibleChange(boolean isVisible,boolean firstVisible) {
        this.isVisible = isVisible;
        if (firstVisible) {
            onLazyLoad();
            isFirstVisible = false;
        }
        if (isVisible && !isFirstOnResume && !isOnResumeVisible) {//isFirstOnResume=false表示fragment预加载,onResume()在可见状态下调用
            isOnResumeVisible = true;
            onResumeVisible();
        }
        if (!isVisible && !isFirstOnResume && isOnResumeVisible) {
            isOnResumeVisible = false;
            onPauseInVisible();
        }
    }

    /**
     * 懒加载(第一次可见)
     */
    protected void onLazyLoad() {

    }

    /**
     * 替代具有不确定性的onResume()(ViewPager可能会让多个fragment执行onResume(),但有些fragment执行后是不可见状态的)
     * 我需要的是执行onResume后,确定是可见状态的方法
     */
    protected void onResumeVisible() {}

    /**
     * 替代具有不确定性的onPause()(ViewPager可能会让多个fragment执行onPause())
     * 我需要的是执行onPause前,确定执行onResume()
     */
    protected void onPauseInVisible() {}
}

源码:https://github.com/wudengwei/TabIndicatorLayout

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A ViewPager is a layout manager that allows the user to swipe left and right to move between pages of data. In the case of a Fragment-based ViewPager, each page is represented by a Fragment. To use a ViewPager with Fragments, you need to do the following: 1. Create a layout file that contains a ViewPager element. 2. Create a Fragment class that will represent a single page in the ViewPager. This class should inflate a layout that contains any UI elements you want to display on the page. 3. Create an adapter class that extends FragmentPagerAdapter or FragmentStatePagerAdapter. This adapter will be responsible for creating and managing the Fragments that are displayed in the ViewPager. 4. Set the adapter on the ViewPager. Here's an example of how to create a Fragment-based ViewPager: 1. Create a layout file that contains a ViewPager element. For example: ``` <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. Create a Fragment class that will represent a single page in the ViewPager. For example: ``` public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_my, container, false); // TODO: Set up UI elements in the layout return view; } } ``` 3. Create an adapter class that extends FragmentPagerAdapter or FragmentStatePagerAdapter. For example: ``` public class MyPagerAdapter extends FragmentPagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // TODO: Return a new instance of MyFragment for the given position return null; } @Override public int getCount() { // TODO: Return the total number of pages return 0; } } ``` 4. Set the adapter on the ViewPager in your Activity or Fragment. For example: ``` ViewPager viewPager = findViewById(R.id.view_pager); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); ``` That's it! You should now have a functioning Fragment-based ViewPager. Of course, you'll need to fill in the TODOs in the code snippets above to actually display content on the pages.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值