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

可見這樣就可以准確統計用戶是否離開或者開始瀏覽界面了。根據這些開始和離開可以統計用戶停留界面的時間等數據。

  

  

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM