<프래그먼트의 수명주기>
프래그먼트는 액티비티 위에 올라가는 것이므로, 프래그먼트의 수명주기도 액티비티의 수명주기에 종속적이다.
그리고 여기에 프래그먼트만 가질 수 있는 독립적인 상태 정보들이 추가되었다.
<프래그먼트가 화면에 보이기 전에 호출되는 상태 메서드>
- onAttach(Activity) : 프래그먼트가 액티비티와 연결될 때 호출됨. 프래그먼트에서 해당 액티비티를 참조하고 싶다면 onAttach 메서드로 전달되는 파라미터를 참조하거나 / getActivity 메서드를 호출하여 반환되는 객체를 참조할 수 있다.
- onCreate(Bundle) : 프래그먼트가 초기화될 때 호출됨.
- onCreateView(LayoutInflator, ViewGroup, Bundle) : 프래그먼트와 관련되는 뷰 계층을 만들어서 리턴함.
프래그먼트와 연결된 액티비티의 상태에 영향을 받는 메서드
- onActivityCreated(Bundle) : 프래그먼트와 연결된 액티비티가 onCreate 매서드의 작업을 완료했을 때 호출됨.
- onStart() : 프래그먼트와 연결된 액티비티가 onStart되어 사용자에게 프래그먼트가 보일 때 호출됨.
- onResume() : 프래그먼트와 연결된 액티비티가 onResume되어 사용자와 상호작용할 수 있을 때 호출됨.
<프래그먼트가 화면에서 보이지 않게 될 때(중지될 때) 호출되는 상태 메서드>
- onPause() : 프래그먼트와 연결된 액티비티가 onPause되어 사용자와 상호작용을 중지할 때 호출됨.
- onStop() : 프래그먼트와 연결된 액티비티가 onStop되어 화면에서 더 이상 보이지 않거나 / 프래그먼트의 기능이 중지되었을 때 호출됨.
- onDestroyView() : 프래그먼트와 관련된 뷰 리소스를 해제할 수 있도록 호출됨.
- onDestroy() : 프래그먼트의 상태를 마지막으로 정리할 수 있도록 호출됨.
- onDetach() : 프래그먼트가 액티비티와 연결을 끊기 바로 전에 호출됨.
위에서 작성한 순서대로 실행된다.
주의할 점 : 프래그먼트 객체가 new 연산자로 만들어졌더라도, 액티비티 위에 올라가기 전까지는 프래그먼트로 동작하지 않는다.
<분할화면 만들기 - 한 화면에 2개의 프래그먼트 배치>
1. 프래그먼트를 두 개 생성한다. (ListFragment, ViewerFragment) 아래와 같이 XML을 배치한다.
2. <ListFragment.java>
package com.example.chapter5_2;
public class ListFragment extends Fragment {
public static interface ImageSelectionCallback{
public void onImageSelected(int position);
}
public ImageSelectionCallback callback;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if(context instanceof ImageSelectionCallback){
callback=(ImageSelectionCallback) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_list, container, false);
Button button = rootView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(callback!=null)
callback.onImageSelected(0);
}
});
Button button2 = rootView.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(callback!=null)
callback.onImageSelected(1);
}
});
Button button3 = rootView.findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(callback!=null)
callback.onImageSelected(2);
}
});
return rootView;
}
}
2 - (1) ImageSelectionCallback
public static interface ImageSelectionCallback{
public void onImageSelected(int position);
}
public ImageSelectionCallback callback;
보면 interface ImageSelectionCallback으로 되어있다. 액티비티마다 다른 이름의 메서드를 만들면 번거롭기 때문에 인터페이스를 정의한 후 액티비티가 이 인터페이스를 구현하도록 만든 것이다.
mainActivity에서 onImageSelected 메서드를 정의한 후, 그 메서드를 호출한다. (화면에서 선택된 버튼에 따라 다른 프래그먼트의 이미지를 바꿔주려면 액티비티 쪽으로 데이터를 전달해야하므로)
callback 변수의 자료형을 ImageSelectionCallback으로 선언함.
2 - (2) onAttach 재정의
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if(context instanceof ImageSelectionCallback){
callback=(ImageSelectionCallback) context;
}
}
onAttach 메서드 안에서는 MainActivity 객체를 참조한 후 ImageSelectionCallback 타입으로 된 callback 변수에 할당한다.
(뭐라는지 모르겠다만 암튼 그렇구나.)
2 - (3) 버튼 onClick 메서드
public void onClick(View view) {
if(callback!=null)
callback.onImageSelected(0);
}
callback이 null이 아니라면 onImageSelected 메서드를 실행한다. 버튼마다 다른 이미지를 보여주기 위해 각각 0, 1, 2의 값을 넣어준다.
3. <ViewerFragment.java>
package com.example.chapter5_2;
public class ViewerFragment extends Fragment {
ImageView imageView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_viewer, container, false);
imageView = rootView.findViewById(R.id.imageView);
return rootView;
}
public void setImage(int resId){
imageView.setImageResource(resId);
}
}
@Nullable이란 null을 허용한다는 의미다. (근데 저걸 굳이 이 코드에 추가해야하나? 없어도 상관없지 않나.. 모르겄다)
public void setImage(int resId){
imageView.setImageResource(resId);
}
setImage 메서드를 통해 이미지를 viewerFragment에 세팅한다.
4. <activity_main.xml>
XML 코드를 수정한다. 최상위 태그를 LinearLayout으로 변경하고, fragment 태그를 2개 추가한다.
width=match_parent, height="0dp", weight="1"로 설정한 다음 각각 name과 id를 설정하면 디자인 화면에서 저렇게 나오는 것을 볼 수 있다.
5. <MainActivity.java>
(이 코드를 작성하기 전에, 처음에 이미지 파일 3개 letters, jibri, lunch를 drawable 폴더에 넣은 상태이다.)
package com.example.chapter5_2;
public class MainActivity extends AppCompatActivity implements ListFragment.ImageSelectionCallback {
ListFragment listFragment;
ViewerFragment viewerFragment;
int[] images = {R.drawable.letters, R.drawable.jibri, R.drawable.lunch};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
listFragment = (ListFragment) manager.findFragmentById(R.id.listFragment);
viewerFragment = (ViewerFragment) manager.findFragmentById(R.id.viewerFragment);
}
@Override
public void onImageSelected(int posistion){
viewerFragment.setImage(images[posistion]);
}
}
5 - (1) 배열로 이미지 설정.
int[] images = {R.drawable.letters, R.drawable.jibri, R.drawable.lunch};
각각 [0], [1], [2]의 위치에 있는 것을 알 수 있다. 이 위치를 이용해서 onImageSelected 메서드가 이미지를 세팅할 수 있게 하는 것.
5 - (2) onImageSelected 메서드
@Override
public void onImageSelected(int posistion){
viewerFragment.setImage(images[posistion]);
}
순서를 정리하면 이렇다.
- ListFragment에서 첫번째 버튼을 누른다. callback.onImageSelected(0);가 실행된다.
- MainActivity에 정의되어있는 onImageSelected 메서드가 실행된다. 이 메서드 안에 있는viewerFragment.setImage(images[0]); 코드가 실행된다. (images[0] = R.drawable.letters)
- setImage 메서드 안에 있는 imageView.setImageResource(R.drawable.letters); 코드가 실행된다.
- letters 이미지가 ViewerFragment에 나타난다.
6. <실행 결과>
버튼을 누르면 이미지가 변경된다.
'TIL > 안드로이드 스튜디오' 카테고리의 다른 글
5장 상단 탭과 하단 탭 만들기 (0) | 2024.12.20 |
---|---|
5장 - 액션바 사용하기 (0) | 2024.12.19 |
5장 - 프래그먼트 기초1 : 2개의 화면전환 (0) | 2024.12.16 |
5장 - Fragment : 액티비티에 프래그먼트 추가하기 (0) | 2024.12.16 |
패키지명 변경하기 (0) | 2024.12.16 |