일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 막무가내
- flutter network call
- 막내의막무가내 rxjava
- 막내의막무가내 플러터
- 막내의막무가내 안드로이드
- 프로그래머스 알고리즘
- 안드로이드 Sunflower 스터디
- 주택가 잠실새내
- 부스트코스에이스
- 막내의막무가내 목표 및 회고
- 막내의막무가내
- 막내의막무가내 SQL
- Fragment
- 막내의막무가내 코틀린 안드로이드
- 2022년 6월 일상
- 안드로이드
- 막내의막무가내 코틀린
- 막내의막무가내 코볼 COBOL
- 막내의막무가내 알고리즘
- 막내의 막무가내 알고리즘
- 막내의막무가내 플러터 flutter
- 막내의막무가내 안드로이드 코틀린
- 주엽역 생활맥주
- 막내의막무가내 안드로이드 에러 해결
- 프래그먼트
- 부스트코스
- 막내의막무가내 일상
- 안드로이드 sunflower
- 막내의막무가내 프로그래밍
- 막내의 막무가내
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] 프래그먼트(fragment) 중요 및 주의할 점 본문
P.S) 2019.05.06
처음공부할 때 작성한 글인데 잘 못 작성한 부분들이 많습니다. 다른글을 읽어보시거나 만약 보신다면 뭐하는코드인지 이부분만 읽어주시면 될 것 같습니다. 지금 다시보니깐 프래그먼트 전환하는 소스코드인데 프래그먼트에서 onAttach할때 activity라는 액티비티객체에 getActivity()를 사용해서 해당 프래그먼트를 참조하고있는 액티비티를 담습니다. (인터페이스를 사용해서 할수도 있는데 객체명이 activity인것을 보니 인터페이스를 사용한것 같지는 않습니다.) 프래그먼트에서 이 객체를 사용해서 activity.onImageChange()라는 메소드를 호출하고 이 메소드는 다른 프래그먼트에서 정의하고 있는 메소드인 setImage()를 불러주는 예제 입니다.
정리하자면, 한 프래그먼트에서 다른프래그먼트와 소통 및 화면전환을 하는 예제입니다. 액티비티와 액티비티 사이에서 인텐트를 사용해서 데이터를 전달받고 전환 및 교류하는 것처럼 프래그먼트와 프래그먼트는 액티비티, 프로그래먼트 매니저를 사용해야합니다.
예제실행순서
1. 프래그먼트1 에서 getActivity()를 사용해 activity에 이 프래그먼트를 참조하고있는 액티비티를 담는다.
2. 프래그먼트1에서 activity는 액티비티를 참조하고있으므로 해당 액티비티에서 정의해논 메소드를 사용할 수 있다. activity.onImageChange() 사용
3. 액티비티의 onImageChange()는 프래그먼트2의 setImage() 메소드를 호출하게 구현되어있다.
fragment2.setImage() 사용
4. 프래그먼트2에는 setImage()메소드가 정의되어있다. (자신의 뷰 배경을 바꾸는)
https://developer.android.com/guide/components/fragments?hl=ko
프래그먼트는 하나의 프래그먼트에서 다른 프래그먼트를 직접 띄울 수 없습니다.
그래서 프래그먼트 매니저가 이러한 사항을 담당합니다.
프래그먼트 매니저는 엑티비티 쪽에 있으므로 다른 프래그먼트를 띄우거나 다른 프래그먼트에 데이터를 전달하고 싶으면 일단 해당 프래그먼트에서 액티비티 쪽으로 데이터를 전달하거나 명령을 전달해야합니다. 즉 사실상 액티비티가 프래그먼트매니저 역할을 한다고도 볼 수 있습니다.
그러면 액티비티 쪽에 메서드를 만들고 그 메서드를 호출하는데 코드의 동일성 및 일관성을 위해 인터페이스를 하나 정의하고 액티비티에서 그 인터페이스를 구현하는 방식으로 하는게 좋습니다.
=>예시(안드로이드개발자 문서)
액티비티로의 이벤트 콜백 생성
어떤 경우에는 프래그먼트로 하여금 액티비티와 이벤트를 공유하게 해야 할 수 있습니다. 이렇게 하기 위한 한 가지 좋은 방법은 프래그먼트 내부의 콜백 인터페이스를 정의한 다음 해당 호스트 액티비티가 이를 구현하도록 하는 것입니다. 액티비티가 인터페이스를 통해 콜백을 수신하면, 필요에 따라 그 정보를 레이아웃 내의 다른 프래그먼트와 공유할 수 있습니다.
예를 들어 어떤 뉴스 애플리케이션에서 액티비티 하나에 프래그먼트가 두 개 있습니다. 하나는 기사 목록을 표시(프래그먼트 A)하고 다른 하나는 기사 하나를 표시(프래그먼트 B)하는 경우 목록 항목이 선택되면 프래그먼트 A가 액티비티에 알려야 프래그먼트 B에 해당 기사를 표시하라고 알릴 수 있습니다. 이 경우, OnArticleSelectedListener
인터페이스는 프래그먼트 A 내부에 선언됩니다.
public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}
그러면 프래그먼트를 호스팅하는 액티비티가 OnArticleSelectedListener
인터페이스를 구현하고 onArticleSelected()
를 재정의하여 프래그먼트 A로부터 발생한 이벤트를 프래그먼트 B에 알립니다. 호스트 액티비티가 이 인터페이스를 구현하도록 하려면 프래그먼트 A의 onAttach()
콜백 메서드(프래그먼트를 액티비티에 추가할 때 시스템이 호출하는 메서드)가 OnArticleSelectedListener
의 인스턴스를 생성해야 합니다. 이때 onAttach()
로 전달되는 Activity
를 형변환하는 방법을 씁니다.
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
...
}
액티비티가 인터페이스를 구현하지 않은 경우, 프래그먼트가 ClassCastException
을 발생시킵니다. 성공 시, mListener
멤버가 액티비티의 OnArticleSelectedListener
구현에 대한 참조를 보유하므로, 프래그먼트 A가 액티비티와 이벤트를 공유할 수 있습니다. 이때 OnArticleSelectedListener
인터페이스가 정의한 메서드를 호출하는 방법을 사용합니다. 예를 들어 프래그먼트 A가 ListFragment
의 확장인 경우, 사용자가 목록 항목을 클릭할 때마다 시스템이 프래그먼트 안의 onListItemClick()
을 호출하고, 그러면 이것이 onArticleSelected()
를 호출하여 해당 이벤트를 액티비티와 공유하는 것입니다.
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.withAppendedId
(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}
onListItemClick()
에 전달된 id
매개변수는 클릭한 항목의 행 ID이며, 액티비티(또는 다른 프래그먼트)가 이것을 사용해 애플리케이션의 ContentProvider
에서 기사를 가져옵니다.
콘텐츠 제공자 사용법에 대한 자세한 정보는 콘텐츠 제공자 문서에서 이용하실 수 있습니다.
액티비티에서 프래그먼트 쪽으로 뭔가 데이터를 주거나 프래그먼트 쪽에 조작을 할 때는 프래그먼트에 메서드를 만들고 액티비티에서 그 메서드를 호출하도록 합니다.
=>ex프래그먼트에서 액티비티에있는 매소드 호출-> 해당 액티비티메소드에서 다른프래그먼트 메소드 호출
프래그먼트1 부분코드
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable 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 v) {
//메인엑티비티 메소드 사용가능
activity.onImageChange(0);
}
});
Button button2 = rootView.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activity.onImageChange(1);
}
});
Button button3 = rootView.findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activity.onImageChange(2);
}
});
return rootView;
}
메인액티비티 부분코드
public void onImageChange(int index){
fragment2.setImage(index);
}
프래그먼트2 부분코드
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable 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 index) {
if (index == 0) {
imageView.setImageResource(R.drawable.a);
} else if (index == 1) {
imageView.setImageResource(R.drawable.b);
} else if (index == 2) {
imageView.setImageResource(R.drawable.c);
}
}
그리고 프래그먼트를 이 프래그먼트에 띄울건지 다른 프래그먼트에 띄울건지는 액티비티에서 결정해주면 됩니다. 뷰페이저(ViewPager)는 그중에 어떤 프래그먼트를 화면에 보여줄 것인지 코드에서 지정할 수도 있다.(메서드 호출을 통해서 몇번째 프래그먼트를 보여줄건지 결정 가능)
뷰페이저가 아니라면 액티비티를 매개로해서 프래그먼트 간의 메서드호출을 통해 구현해야합니다.
=> ex메인액티비티에서
ViewPager pager;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//1=> 2번쨰 프래그먼트를 보여주라
pager.setCurrentItem(1);
}
});
'안드로이드 > 자바 & Previous' 카테고리의 다른 글
[안드로이드] 인텐트 기본 사용방법 (intent) (0) | 2019.03.01 |
---|---|
[안드로이드] asynctask 사용법 예제(이해하기쉽게 정리) + 병렬 실행 (9) | 2019.02.21 |
[안드로이드] 뷰페이저(ViewPager) 학습 (2) | 2019.02.12 |
[안드로이드] 프래그먼트(fragment) 예제 + FrameLayout (14) | 2019.02.09 |
[안드로이드] 액션바(actionBar) 없애기, 타이틀바 없애기 (8) | 2019.02.08 |