본문 바로가기

안드로이드스튜디오

안드로이드 스튜디오 프래그먼트 개념정리

728x90
반응형

* 프래그먼트는 레이아웃이 중복되는 문제를 해결하기 위해 부분 화면을 위한 레이아웃이나 소스 코드를 한 번만 정의하고 재사용할 수 있도록 만든 것이다.

 

* 코드의 복잡성을 해결하기 위해 각 부분 화면의 코드를 분리시킨 것이다.

 

* 가장 큰 목적은 분할된 화면들을 독립적으로 구성하고 그 상태를 관리하는 데 있다.

 

* 똑같이 XML 레이아웃으로 만들지만 액티비티에 사용되면 시스템에서 관리하는 화면이고, 프래그먼트에서 사용되면 단순히 액티비티 위에 올라가는 화면의 일부, 즉'부분 화면'이 된다.

 

* 프레그먼트는 항상 액티비티 위에 올라가 있어야 한다.

왜냐하면 액티비티로 만든 화면을 분할한 뒤 각각의 부분 화면을 프래그먼트로 만들고 그 프래그먼트를 독립적으로 관리하는 것이 목표이기 때문이다.

따라서 프로그먼트가 제대로 동작하는 시점은 프래그먼트가 메모리에 만들어진 시점이 아닌 액티비티에 올라가는 시점이다.

* 왼쪽 그림은 액티비티가 동작하는 방식, 오른쪽 그림은 프래그먼트가 동작하는 방식

 

* 액티비티는 앱 구성 요소이므로 안드로이드 시스템에서 관리한다.

좀 더 구체적으로는 액티비티 매니저가 액티비티의 동작 순서나 처리 방식을 결정한다. 

또한 액티비티가 시스템에서 관리되기 때문에 시스템이 이해하는 형식으로 명령이나 데이터를 만들어 보내야 하는데, 인텐트가 그 역할을 한다.

즉, 액티비티를 관리하는 시스템 객체는 액티비티 매니저이며, 이 액티비티 매니저에 의해 액티비티가 독립적으로 동작할 수 있다.

 

* 프로그먼트는 액티비티와 동작이 유사한 것을 볼 수 있다.

액티비티는 액티비티 매니저가 관리했다면 프래그먼트는 프래그먼트 매니저가 관리한다.

 

* 인텐트는 시스템에서 이해하는 객체인데 그것을 프래그먼트와 액티비티 사이에서 전달하게 만드는 것은 바람직하지 않다.

 

* 액티비티는 시스템에서 관리하지만 프래그먼트는 액티비티 위에 올라가 있어 액티비티를 전환하지 않고도 훨씬 가볍게 화면 전환 효과를 만들 수 있다.

* 프래그먼트 사용 목적은 부분 화면을 독립적으로 사용하기 위해서이고 액티비티를 본떠 만든 것이다.

즉, 액티비티라는 것이 하나의 XML 레이아웃과 하나의 자바 소스 파일로 동작하는 것처럼 프래그먼트도 하나의 XML 레이아웃과 하나의 자바 소스 파일로 동작하게 만든다.

* 프래그먼트도 부분 화면이므로 화면에 뷰를 배치할 때는 XML 레이아웃으로 만든다. 그다음에는 프래그먼트를 위한 자바 소스를 만든다. 프래그먼트를 위한 자바 소스는 Fragment 클래스를 상속하여 만들 수 있다.

 

 * [Code] FragmentManager

public abstract FragmentTransaction beginTransaction()
// 프래그먼트를 변경하기 위한 트랜잭션을 시작함

public abstract Fragment findFragmentById(int id)
// ID를 이용해 프래그먼트 객체를 찾음

public abstract Fragment findFragmentByTag(String tag)
// 태그 정보를 사용해 프래그먼트 객체를 찾음

public abstract boolean executePendingTransactions()
// 트랜잭션은 commit 매서드를 호출하면 실행되지만 비동기(asynchronous)방식으로 실행되므로
// 즉시 실행하고 싶다면 이 메서드를 추가로 호출해야 함

+

Framentmanager 객체는 프래그먼트를 액티비티에 추가(add), 다른 프래그먼트로 바꾸거나(repleace) 또는 삭제(remove)할 때 주로 사용할 수 있으며 getFragmentManager 메서드를 호출하면 참조할 수 있다.

 

* 프래그먼트듸 대표적인 특성

 특성 설명
뷰 특성 뷰 그룹에 추가되거나 일부가 될 수 있음
(뷰에서 상속받은 것은 아니며 뷰를 담고 있는 일종의 틀임)
액티비티 특성 액티비티처럼 수명주기(Lifecycle)를 가지고 있음
(컨텍스트 객체는 아니며 수명주기는 액티비티에 종속됨)

 

* 프래그멘드를 메인 액티비티에 추가하는 방법은 두 가지이다.

1. 메인 액티비티의 XML 레이아웃에 태그로 추가하는 방법

2. 메인 액티비티의 소스 코드에서 추가하는 방법

 

* 프래그먼트를 만들어 사용하는 간단한 과정

1. 프래그먼트를 위한 XML 레이아웃만들기

2. 프래그먼트 클래스 만들기

3. 플래그먼트를 액티비티의 XML 레이아웃에 추가하기

 

* 화면에 뷰를 추가하는 방법

1. XML 레이아웃에 추가하는 방법

2. 자바 소스 코드로 추가하는 방법

코드에서 프래그먼트를 추가할 때는 프래그먼트 매니저에게 요청해야 한다.

 

* 메인 프래그먼트 안에 표시되는 최상위 레이아웃은 인플레이션을 통해 참조된 rootView 객체이다.

최상위 레이아웃(rootView)은 메인 프래그먼트 안에 들어 있는 것이고 메인 프래그먼트는 이 레이아웃을 화면에 보여주기 위한 틀이라고 생각할 수 있다. 그래서 rootView의 findViewById 메서드를 사용하여 레이아웃에 들어 있는 버튼 객체를 찾아낼 수 있다.

그리고 이 객체의 setOnClickListener메서드를 호출하여 리스너를 등록하면 버튼이 클릭되었을 때 이벤트를 처리할 수 있다.

onClick 메서드 안에서는 MainActivity 객체를 참조한 후 onFragmentChanged 메서드를 호출하도론 한다. 

onFragmentChanged 메서드는 메인 액티비티에 새로 추가할 메서드로 프래그먼트 매니저를 이용해 프래그먼트를 전환하는 매서드이다.

 

public class MainFragment extends Fragment {
	
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
    	Bundle savedInstanceState){
        
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_main,
        	container, false);
            
        Button button = rootView.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){
        	@Override
            public void onClick(View v){
            	MainActivity activity = (MainActivity) getActivity();
                activity.onFragmentChanged(0);
            	}
        	});
            return rootView;
        }
}

 

* 이렇게 코드를 입력한 이유는 프래그먼트가 액티비티를 본떠 만들었고 액티비티 관리를 시스템에서 하는 것처럼 프래그먼트 관리를 액티비티가 하기 때문에 액티비티에서 프래그먼트를 전환하도록 만들어야 하기 때문이다.

즉, 하나의 프래그먼트에서 다른 프래그먼트를 직접 띄우는 것이 아닌 액티비티를 통해 띄어야 한다.

 

* 프래그먼트에서는 getActivity 메서드를 호출하면 프래그먼트가 올라가 있는 액티비티가 어떤 것인지 확인할 수 있다.

이제 액티비티에 onFragmentChanged 메서드를 포함한 나머지 필요한 코드를 MainActivity.java 파일에 추가한다.

 

public class MainActivity extends AppCompatActivity {
	MainFragment mainFragment;
    MainFragment menuFragment;
    
    @Override
    protected void onCreate (Bundle savedInstanceState){
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        maintFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
        menuFragment = new MenuFragment();
    }
    
    public void onFragmentChanged(int index){
    	if(index == 0){
        	getSupportFragmentManager().beginTransaction().replace(R.id.container.menuFragment).commit();
        }else if (index==1){
        	getSupportFragmentManager().beginTransaction().replace(R.id.container,mainFragment).commit();
        }
    }
}

 

* 메인 프래그먼트는 액티비티를 위한 activity_main.xml 파일에 추가되어 있으므로 id를 사용해서 찾아야 한다.

하지만 프래그먼트는 뷰가 아니라서 Activity 클래스에 있는 findViewById 메서드로 찾으루 ㅅ 없다.

대신 프래그먼트를 관리하는 FragmentManager 객체의 findFagmentById 메서드를 사용해서 찾을 수 있다.

메인 프래그먼트는 findFragmentById 메서드를 사용해 찾은 후 변수에 할당하고 메뉴 프래그먼트는 new 연산자를 사용해 새로운 객체로 만들어 변수에 할당합니다.

 

* OnFragmentChanged 메서드는 프래그먼트에서 호출할 수 있도록 정의한 것으로 파라미터로 전달된 정수의 값이 0이면 메인 프래그먼트가 보이게 하고, 1이면 메뉴 프래그먼트가 보이게 할 수 있다.

이 매서드 안에서는 FragmentManager 객체의 replace 메서드를 사용해 프래그먼트를 바꾸도록 입력합니다. replace 메서드로 전달되는 첫 번째 파라미터는 프래그먼트를 담고 있는 레이아웃의 id가 되어야 하므로 R.id.container를 전달한다.

 

* 메인 액티비티에서 프래그먼트를 다루기 위해서는 먼저 getSupportFragmentManager 메서드를 호출하여 매니저 객체를 참조한다.

 

//[Reference]
public FragmentManager getSupportFragmentManager()

 

* 프래그먼트 매니저는 프래그먼트를 다루는 작업을 해 주는 객체로 프래그먼트 추가, 삭제 또는 교체 등의 작업을 할 수 있다.

그런데 이런 작업들은 프래그먼트를 변경할 때 오류가 생기면 다시 원래 상태로 돌릴 수 있어야 하므로 트랜잭션 객체를 만들어 실행한다.

 

* 트랜잭션 객체는 beginTransaction 메서드를 호출하면 시작된고 commit 메서드를 호출하면 실행된다.

반응형