ViewPager 완전정복 - setOffscreenPageLimit, setUserVisibleHint

Posted by ITPangPang
2016. 10. 31. 23:19 안드로이드(android)/ViewPager


ViewPager 완전정복

(setOffscreenPageLimit, setUserVisibleHint)



이번글은 제목에도 나와있듯이 setOffscreenPageLimit와

    setUserVisibleHint에 대해서 알아보도록 하겠습니다.


ㆍ 코드는 이전글에서 만들었던 코드를 그대로 가져다가

    사용할 예정입니다.




setOffScreenPageLimit 어디다가 쓰나?


첫번째 글 마지막부분에서

제가 이렇게 써놨었습니다.



현재 보이는 페이지 좌우만

생성해놓고 사용하는 구조이다.


이게 무슨말인지 한번 보겠습니다.



마우스로 Swipe를 하다보니

깔끔하게 넘어가지 않은 부분이

있지만..


위의 gif를 보게되면

가운데 탭인 채팅방의

숫자카운터는 계속 유지되는데

친구, 설정탭의 숫자카운터는

초기화 되는 모습을 볼 수 있습니다.


위에서 말했던 그대로입니다.


앱을 실행하면

첫번째 친구탭에서는

다음탭인 채팅방탭을 

미리 생성해놓습니다.


그리고 채팅방탭

넘어왔을때는 채팅방탭 기준

좌우(이전,다음)페이지인

친구, 설정탭을 생성하게 됩니다.

친구탭은 미리 생성되있으므로

설정탭만 생성하면 되겠죠


그리고 이제 3번째

설정탭을 누르게되면

이전페이지인 채팅방탭

생성(준비)되어있으면 됩니다.


이때, 첫번째탭친구탭

준비하고(그려놓고) 있을 필요가 없습니다.

그러므로 페이지를 파괴해놓습니다.

(이때 숫자카운터 한 내용은 싹 날라가죠)


그리고 3번째에서

다시 2번째탭으로

넘어왔을때, 첫번째탭이

그려져있어야 하는데

파괴된 상태이므로

새로 생성하게됩니다


이런식으로 바로

좌우(이전,다음)페이지와

연결되어 있지 않을때

화면에 그려놓은 내용은

싹 초기화 하게 되는 것입니다


두번째 탭은 어느탭에 있던

항상 좌우에 포함되므로 계속

유지되게 되는것 입니다.



그럼 모든 탭의 화면을 항상

유지하고 싶다면 어떻게

하면 될까요?


바로!!

setOffscreenPageLimit

사용하면 됩니다


사용방법은 간단합니다

vp.setAdapter(new pagerAdapter(getSupportFragmentManager()));
vp.setOffscreenPageLimit(2);
vp.setCurrentItem(0);


vp는 ViewPager입니다.

setOffscreenPageLimit를 통하여

좌우 몇개의 페이지를 그려놓고(준비)

있을지 설정해 줄 수 있습니다.


위와 같이 2라고 적으면

좌 2, 현재, 우2

총 5페이지가 그려져(준비)있는

상태겠죠


결과를 보겠습니다


처음 결과와 다르게

값이 초기화되지 않고

유지되는 것을 확인 할 수 있습니다.


그럼 화면으로 말고 코드로 확인해보자!


그럼 위에서 한 말을

코드를 통해서 확인해보겠습니다.


확인을 해보기 위해서

각 Fragment의

onCreateView

onDestroyView에 로그를

달아보도록 하겠습니다.


public class FirstFragment extends Fragment
{
public FirstFragment()
{
}
TextView tv;
int i = 0;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Log.d("ITPANGPANG","onCreateView(First)");
RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.fragment_first, container, false);
tv = (TextView)layout.findViewById(R.id.tv);
Button btn = (Button)layout.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
i++;
tv.setText(""+i);
}
});
return layout;
}

@Override
public void onDestroyView()
{
Log.d("ITPANGPANG","onDestroyView(First)");
super.onDestroyView();
}
}


자 다른 부분은

볼 것 없고


onCreateViewonDestoryView

Log를 추가한 것만 확인하시면 됩니다.


이런식으로 Second, Third Fragment에도

추가시킨 후에 앱을 다시 돌려보도록

하겠습니다


먼저

setOffscreenPageLimit를

추가시키기 전입니다.


[앱 실행시]

1, 2번 탭이 생성되었습니다

(왜 Second가 먼저인지는 나중에 찾아봐야겠네요)



[두번째 탭 이동]

두번째 탭으로 이동하니

세번째탭이 생성되는 것을

확인 할 수 있습니다


[세번째 탭 이동]

세번째 탭으로 이동하니

첫번째 Fragment가 파괴되는

것을 확인 할 수 있었습니다.


[세번째 탭 -> 두번째 탭 -> 첫번째탭]


세번째 탭에서 

다시 차례대로

두번째, 첫번째탭으로 돌아왔을때의

로그를 확인 해보니


두번째 탭으로 왔을때 : onCreateView(First)

첫번째 탭으로 왔을때 : onDestroyView(Third)

의 결과를 얻을 수 있었습니다.



이제

setOffscreenPageLimit(2)를

추가하고 확인해보겠습니다.


[앱 실행시]


실행하자마자

모든 Fragment가 생성되는것을

확인 할 수 있었습니다.


[두번째 탭 이동]

변화 없음


[세번째 탭 이동]

변화 없음


[세번째 탭 -> 두번째 탭 -> 첫번째탭]

변화 없음


뭐 당연한 결과였습니다.

모든 페이지가 그려져있으므로

(항상 준비되어 있어야 하므로)


파괴되는 Fragment도 없어야 합니다


그럼 setOffscreenPageLimit(0)을 넣으면?


자 만약에

setOffscreenPageLimit

0값을 넣으면 어떻게 될까요?


위에서 설명한대로 라면

좌우(이전,다음) 준비되는 페이지가

없어야 하므로..


현재 눈에 보이는 페이지만

그려져있고, 다음탭으로 넘어갈때

그때서야 다음페이지가 생성될까요?


결과만 말씀드리면

위의 예상결과는 틀린답입니다.


실제로 0값을 넣어봐도

1값을 넣은 것과 동일한 결과가

나옵니다.

(앱이 죽을수도 있는지는 모르겠습니다)


과연

이 부분이 대단히 중요한

부분일까요?


하나 예를 들어보겠습니다.

만약 첫번째 탭에서

어떤 변화를 줬을때

그 변화가 두번째 탭에

영향을 끼쳐야 하는 상황이라면?


ViewPager에 담겨있는


첫번째 페이지에서

구매할 사과의 갯수를 고를 수 있고


두번째 페이지를 넘어왔을때

그 갯수에 해당하는 사과의

가격이 자동으로 찍혀있어야 하는

상황이라면?


어떻게 해야할까요?

두번째 탭을 넘어올때

첫번째 입력한 사과의 갯수를 받아와서

화면에 뿌려줘야 하는데


위에서 로그를 찍어봐서 알겠지만

첫번째에서 두번째 탭으로 넘어올때

onCreateView를 타지않습니다

(미리 그려져있는데 다시 그릴 필요가 없으니까요)


그렇다면 이 사과의 갯수는

어떻게 받을 수 있을까요?


이 상황을 해결하기 위해서는

setUserVisibleHint

바로 이놈을 사용해줘야 합니다.


과연 이놈이 무엇인지는

다음글에서 알아보도록 하겠습니다.


setUserVisibleHint를 사용한 예제


위 예를 든 부분은

제가 글을 잘 못쓰기도하고

잘 썼다고 해도 이해하기 어려울 수 있습니다.


그러므로 다음글에서

결과화면과 로그를 동시에 보면서

도대체 무슨말을 한것이었는지

알아보도록 하겠습니다.