Fragment可见性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class ExampleFragment extends Fragment{
/**
* 当fragment与viewpager、FragmentPagerAdapter一起使用时,切换页面时会调用此方法
*
* @param isVisibleToUser 是否对用户可见
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
boolean change = isVisibleToUser != getUserVisibleHint();
super.setUserVisibleHint(isVisibleToUser);
// 在viewpager中,创建fragment时就会调用这个方法,但这时还没有resume,为了避免重复调用visible和invisible,
// 只有当fragment状态是resumed并且初始化完毕后才进行visible和invisible的回调
if (isResumed() && change) {
if (getUserVisibleHint()) {
onVisible();
} else {
onInvisible();
}
}
}

/**
* 当使用show/hide方法时,会触发此回调
*
* @param hidden fragment是否被隐藏
*/
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
onInvisible();
} else {
onVisible();
}
}


@Override
public void onResume() {
super.onResume();
// onResume并不代表fragment可见
// 如果是在viewpager里,就需要判断getUserVisibleHint,不在viewpager时,getUserVisibleHint默认为true
// 如果是其它情况,就通过isHidden判断,因为show/hide时会改变isHidden的状态
// 所以,只有当fragment原来是可见状态时,进入onResume就回调onVisible
if (getUserVisibleHint() && !isHidden()) {
onVisible();
}
}

@Override
public void onPause() {
super.onPause();
// onPause时也需要判断,如果当前fragment在viewpager中不可见,就已经回调过了,onPause时也就不需要再次回调onInvisible了
// 所以,只有当fragment是可见状态时进入onPause才加调onInvisible
if (getUserVisibleHint() && !isHidden()) {
onInvisible();
}
}

private void onInvisible() {
}

private void onVisible() {
initData();
}
}

补充 :

setUserVisibleHint 为什么只在 Viewpager 有效?

实际上查看 setUserVisibleHint 的实际调用方,只有 FragmentPagerAdapter 和 FragmentStatePagerAdapter,也即 ViewPager 的适配器有调用。