zoukankan      html  css  js  c++  java
  • setUserVisibleHint-- fragment真正的onResume和onPause方法

    现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点,如下图就是fragment的生命周期

    但是fragment和activity不同的是当调用本身的onResume和onPause方法的时候可能并不是当前的fragment在显示,例如当加载下面这张图时,当我打开MainActivity时显示的是第一个fragment 但此时调用的方法步骤如下:

    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
    08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated

    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()  

    可见此时虽然用户看到的是第一个fragment 但第二个fragment onAttech onCreate onCreateView onActivityCreater onStart(“这个我没油打印log”)onResume 方法已经调用,这会导致如果我们要统计用户更喜欢哪个fragment的内容时,虽然fragment已经创建并且onResume但其实并没有显示这一页,那么是什么原因呢,这是因为v4包下的viewpager,为了让用户在切换过程中不会卡顿,谷歌官方默认当创建第一个fragment方法时回创建第二个fragment以确保用户滑动时第二个view已经被创建,保持viewPager的平滑滑动效果。

    翻阅谷歌api发现viewpager有一个方法即 setOffscreenPageLimit。但当在viewpager设置以下代码

    viewPager.setOffscreenPageLimit(0);
    

    运行时打印的log和上面完全一致,即就算你设置只加载一个fragment还是会加载第二个fragment,原因是setOffscreenPageLimit中的源码时这样写的

    public void setOffscreenPageLimit(int limit) {  
            if (limit < DEFAULT_OFFSCREEN_PAGES) {  
                Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +  
                        DEFAULT_OFFSCREEN_PAGES);  
                limit = DEFAULT_OFFSCREEN_PAGES;  
            }  
            if (limit != mOffscreenPageLimit) {  
                mOffscreenPageLimit = limit;  
                populate();  
            }  
        }  
    

    这个 DEFAULT_OFFSCREEN_PAGES 定义如下 private static final intDEFAULT_OFFSCREEN_PAGES;

    就是如果你设置为0 也没用。!!!

    为了解决判断是否fragment当前显示问题 可以在fragment重写 setUserVisibleHint(boolean isVisibleToUser)

    在fragment添加log日志

    public class Fragment1 extends Fragment {  
        private static final String TAG = "Fragment1";  
      
        @Override  
        public void onAttach(Activity activity) {  
            super.onAttach(activity);  
            L.v(TAG, "onAttach");  
        }  
      
        @Override  
        public void setUserVisibleHint(boolean isVisibleToUser) {  
            L.v(TAG, "setUserVisibleHint " + isVisibleToUser);  
        }  
      
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            L.v(TAG, "onCreate");  
        }  
      
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
            L.v(TAG, "onCreateView");  
            View view = inflater.inflate(R.layout.fragment_layout,null);  
            TextView tv = (TextView) view.findViewById(R.id.tv1);  
            tv.setText(TAG);  
            return view;  
        }  
      
        @Override  
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
            super.onActivityCreated(savedInstanceState);  
            L.v(TAG,"onActivityCreated");  
        }  
      
        @Override  
        public void onResume() {  
            super.onResume();  
            L.v(TAG, "onResume()");  
        }  
      
        @Override  
        public void onPause() {  
            super.onPause();  
            L.v(TAG,"onPause");  
        }  
      
        @Override  
        public void onStop() {  
            super.onStop();  
            L.v(TAG,"onStop");  
        }  
    

    启动activity打印日志如下:

    08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
    08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
    08-11 11:33:36.157    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
    08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()

    当切换到第二个fragment时打印日志:

    08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
    08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
    08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
    08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onAttach
    08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreate
    08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
    08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
    08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onResume()

    可见当fragment显示时回调用方法 setUserVisibleHint中的isVisibleToUser = true 当fragment被切换隐藏时回 isVisibleToUser = false;

    所以当我们要统计是否用户看到一个fragment时可以执行一下代码

    @Override  
    public void setUserVisibleHint(boolean isVisibleToUser) {  
            L.v(TAG, "setUserVisibleHint " + isVisibleToUser);  
            if (isVisibleToUser) {  
                //统计代码 或者 fragment显示操作  
            } else {  
                  
            }  
     }  
    

    同时根据这个方法还可以进行数据的延迟加载,后面再写。

    今天又看了一下发现单纯的执行上面的代码是有问题的,因为如果我们在else中认为用户是离开界面其实是不对的,因为根据启动第一个Fragment的log日志

    08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
    08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
    08-11 11:33:36.157    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
    08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
    08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
    08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
    08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()

    第一次setUserVisibleHint 方法 isVisibleToUser 是false 但其实这个时候只是还未初始化,并不是用户已经浏览界面准备离开,于是这里我们需要一个辅助标记变量具体代码如下:

    /** 
         * 判断是否是初始化Fragment 
         */  
        private boolean hasStarted = false;  
        @Override  
        public void setUserVisibleHint(boolean isVisibleToUser) {  
            super.setUserVisibleHint(isVisibleToUser);  
            L.v(TAG, "setUserVisibleHint " + isVisibleToUser);  
            if (isVisibleToUser) {  
                hasStarted = true;  
                L.v(TAG,"开始界面");  
            } else {  
                if (hasStarted) {  
                    hasStarted = false;  
                    L.v(TAG,"结束界面");  
                }  
            }  
        }  
    

    当我们启动MainActivity时 Log打印如下:

    08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
    08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
    08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onAttach
    08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreate
    08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
    08-13 17:55:45.860  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 开始界面
    08-13 17:55:45.860  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
    08-13 17:55:45.870  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onResume()
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onAttach
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreate
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
    08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onResume()

    切换到第二个fragment时,此时离开第一个fagment  log打印如下

    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 结束界面
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 开始界面
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onAttach
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreate
    08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
    08-13 17:57:04.320  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
    08-13 17:57:04.320  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onResume()

    切换到第三个fragment时,此时离开第二个fragment log打印如下:

    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 结束界面
    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint true
    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ 开始界面
    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onPause
    08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onStop

    可见这样就可以准确统计用户是否离开或者开始浏览界面了。根据这些开始和离开可以统计用户停留界面的时间等数据。

      

      

     

      

      

  • 相关阅读:
    [Linux Sets] hosts, wlan and other net-rele
    [Source] 温柔的图片
    [CATARC_2017] 第三周 & 残四周
    [CATARC_2017] 第二周
    ubuntu 安装
    知规矩者混天下言。
    python+selenium的web自动化测试之二(Jenkins自动执行)
    python+selenium的web自动化测试之一(手工执行)
    Python 入门小实例笔记
    Web安全测试工具 Burp Suit 使用简介
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/6690935.html
Copyright © 2011-2022 走看看