본문 바로가기

PROGRAMING/Android

Fragment와 BackStack 이슈 (show,hide 버그로 보여짐) replace 사용.

안드로이드 4.0에서 선보인 Fragment예제를 보다 보면


FragmentManager와 FragmentTransaction을 이용해서  Fragment를 붙이게 되는데

예제를 그대로 따라 하다보면 몇가지 오류를 범하게되었다


FragmentBackStack_issue_1.zip



 버튼 1

  버튼 2

  버튼 3

 


FragmentLayout 





@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button btnFisrt = (Button)findViewById(R.id.btnFirst);

Button btnSecond = (Button)findViewById(R.id.btnSecond);

Button btnThree = (Button)findViewById(R.id.btnThree);

btnFisrt.setOnClickListener(this);

btnSecond.setOnClickListener(this);

btnThree.setOnClickListener(this);

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.add(R.id.frameLayout,mFirstFragment,FRAGMENT_FIRST);

ft.add(R.id.frameLayout,mSecondFragment,FRAGMENT_SECOND);

ft.add(R.id.frameLayout,mThreeFragment,FRAGMENT_THREE);

ft.hide(mFirstFragment);

ft.hide(mSecondFragment);

ft.hide(mThreeFragment);

ft.commit();

}



@Override

public void onClick(View v) {

if(v.getId()==R.id.btnFirst) {

Log.d(CLASSNAME,"onClick R.id.btnFirst");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.show(mFirstFragment);

ft.hide(mSecondFragment);

ft.hide(mThreeFragment);

ft.addToBackStack(null);

ft.commit();

} else if(v.getId()==R.id.btnSecond) {

Log.d(CLASSNAME,"onClick R.id.btnSecond");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.hide(mFirstFragment);

ft.show(mSecondFragment);

ft.hide(mThreeFragment);

ft.addToBackStack(null);

ft.commit();

} else if(v.getId()==R.id.btnThree) {

Log.d(CLASSNAME,"onClick R.id.btnThree");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.hide(mFirstFragment);

ft.hide(mSecondFragment);

ft.show(mThreeFragment);

ft.addToBackStack(null);

ft.commit();

}

}



1

 2

3

 4

 1번 클릭

 2번 클릭   3번 클릭

back key


시에 아래와 같이 화면이 겹쳐지는 현상이 발생하였다.



첫번째 이슈 문제1,2번 Fragment가 겹쳐보임


위처럼 1,2번 Fragment가 겹치는 현상이 발생한다.

겹치는 것을 확인하기 위해 FrameLayout을 LinerLayout으로 변경해보았다.


 1

 2  3
 1번 클릭

 2번 클릭

 3번 클릭

 LinerLayout으로 대체 후 확인1번 Fragment가 pop 된 상태 2,3번 Fragment가 보임 의도 대로 였으면 아무 것도 보이면 안되었다. LinerLayout으로 대체 후 확인2번 Fragment가 pop 된 상태 1,3번 Fragment가 보임 의도대로 였으면 1번 Fragment가 보여야 한다. LinerLayout으로 대체 후 확인2번 Fragment가 pop 된 상태 1,3번 Fragment가 보임 의도 대로 였으면 2번 Fragment가 보여야 한다.

3번 Back Key>Back Key

>Back Key

3번 Back Key>Back Key


3번까지 클릭하고 

back key를 눌렀을 경우

위 처럼 화면이 이상하게 나타난다.

3번 클릭하고 back key를 클릭하면 3번 FragmentTransection이 pop되어 3번 내용이 hide되는 것으로

보이나 1,2번 Fragment내용이 보이는  예상하지 못한 결과를 보였다.


3번 클릭하고 back key>back key 를 클릭하면 2번 FragmentTransection까지 pop이 되면서

2번이 hide되고 1,3번 화면이 보이는 역시 예상하지 못한 결과를 보인다.


3번 클릭하고 back key>back key>back key를 클릭하면 1번 FragmentTransction까지 pop되면서

1번이 hide되고 2,3번 화면이 보이는 역시 예상하지 못한 결과를 보인다.


예상했던 것은 pop 되면 그전 구성한 화면이 표시되는 것을 기대했으나 그렇게 되지 않았다.

안드로이드의 버그로 보인다. show,hide의 이전 상태를 제대로 기억하지 못하는 것 같다.



add되신 replace를 사용하여 구성하여 보았다.


FragmentBackStack_issue_1_fixed.zip


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button btnFisrt = (Button)findViewById(R.id.btnFirst);

Button btnSecond = (Button)findViewById(R.id.btnSecond);

Button btnThree = (Button)findViewById(R.id.btnThree);

btnFisrt.setOnClickListener(this);

btnSecond.setOnClickListener(this);

btnThree.setOnClickListener(this);

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.add(R.id.frameLayout,mFirstFragment,FRAGMENT_FIRST);

ft.commit();

}


최초 onCreate에 add를 하여 첫번째 Fragment가 보이도록 했다.

@Override

public void onClick(View v) {

if(v.getId()==R.id.btnFirst) {

Log.d(CLASSNAME,"onClick R.id.btnFirst");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.replace(R.id.frameLayout,mFirstFragment,FRAGMENT_FIRST);

ft.addToBackStack(null);

ft.commit();

} else if(v.getId()==R.id.btnSecond) {

Log.d(CLASSNAME,"onClick R.id.btnSecond");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.replace(R.id.frameLayout,mSecondFragment,FRAGMENT_SECOND);

ft.addToBackStack(null);

ft.commit();

} else if(v.getId()==R.id.btnThree) {

Log.d(CLASSNAME,"onClick R.id.btnThree");

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.replace(R.id.frameLayout,mThreeFragment,FRAGMENT_THREE);

ft.addToBackStack(null);

ft.commit();

}

}


이후 버튼클릭시 replace를 하여 이미 멤버변수로 할당 되어있는 Fragment 객체들로 replace를 시킨다.


 1  2  3

 1번 클릭

 2번 클릭  3번 클릭

replace를 사용했을 때 1번 Fragment pop 최초 1번 Fragment가 add된 이후 1번 버튼을 클릭하였으므로 1번이 Fragment pop 되어도 1번 Fragment가 보여진다. 정상 동작

replace를 사용했을 때 2번 Fragment pop 1번 Fragment가 보여진다. 정상 동작

replace를 사용했을 때 3번 버튼 까지 클릭하고 back key 시 3번 Fragment pop 2번 Fragment가 보여진다. 정상 동작

 3번 Back Key>Back Key

>Back Key

 3번 Back Key>Back Key

 3번까지 클릭하고 

back key를 눌렀을 경우


위 처럼 나타나면 해당 동작은 정상동작이다.


위 와 같은 의도로 사용될때 현재 4.12 JB버전 까지는 add,show,hide보다 replace를 이용하는 것이

맞는 것으로 보인다.