Bundle
Bundle(번들): key, value 쌍으로 데이터를 저장하는 일종의 Map 클래스
Bundle과 Intent 차이
Bundle: 단순히 데이터 전달을 위한 직렬화 객체, 주로 Fragment간 데이터 전달에 사용
Intent: 특정 컴포넌트를 실행하고 원하는 데이터를 전달하기 위한, Activity간 또는 Activity-Fragment간에 사용
1. 일단 첫 번째 프래그먼트 클래스 내에 정적변수로 Bundle을 선언한다
: static변수는 프로그램 실행 시 할당되고 종료시 파괴되는 변수이기 때문에,
프래그먼트가 여러번 실행되더라도 변수의 선언 및 초기화는 한번만 이루어짐
public class Fragment1 extends Fragment{
EditText et_name;
static Bundle bundle;
}
2. Fragment액티비티에서 사용자에게 데이터를 받아온다.
@Override
public void onResume() {
super.onResume();
bundle = new Bundle(); //번들 생성
}
//프래그먼트 처음 시작하는 생명주기
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.setting_name, container, false);
et_name = rootView.findViewById(R.id.et_name); //데이터 받기
return rootView;
}
3. 프래그먼트의 생명주기 중 하나인 onPause()을 상속해 bundle에 데이터를 넣는다.
@Override
public void onPause() {
super.onPause();
if(et_name.getText().toString().equals("")){
//입력 필드가 공백일 때 작동 안함
} else{
bundle.putString("userName", et_name.getText().toString()); //bundle에 값넣기
}
}
4. 다른 프래그먼트에서 첫번째 프래그먼트의 번들을 받아온다.
public class Fragment2 extends Fragment {
EditText et_home;
Bundle bundle;
@Override
public void onResume() {
super.onResume();
//Fragment1의 Bundle 가져오기
Fragment1 frag_1 = new Fragment1();
bundle = frag_1.bundle;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.setting_home, container, false);
et_home = rootView.findViewById(R.id.et_home);
return rootView;
}
@Override
public void onPause() {
super.onPause();
if(bundle != null){
bundle.putString("userHome", et_home.getText().toString()); //번들에 데이터 추가
}
}
}
5. 이런식으로 사용자로부터 데이터를 받아올때마다 Fragment1의 bundle을 가져와서 데이터를 추가저장한다
6. 마지막 프래그먼트에서 오류 검증이나 DB작업을 해준다.
: 또는 뷰페이저를 담은 액티비티의 onDstroy()생명주기를 이용하는 것도 가능
public class Fragment5 extends Fragment {
EditText et_phone;
Bundle bundle;
@Override
public void onResume() {
super.onResume();
//Bundle가져오기
Fragment1 frag_1 = new Fragment1();
bundle = frag_1.bundle;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.setting_phone, container, false);
et_phone = rootView.findViewById(R.id.et_phone);
et_phone.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
Button btn_done = rootView.findViewById(R.id.btn_done);
btn_done.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View view) {
//오류 검증
if (bundle.getString("userName") == null || bundle.getString("userName").equals("")){
StartActivity.fragmentChange(0);
Toast.makeText(getActivity(), "이름을 입력해주세요!", Toast.LENGTH_SHORT).show();
} else if{...}
//DB작업
getActivity().finish();
}
);
return rootView;
}
7. [참고] 프래그먼트의 데이터 오류검증을 위한 프래그먼트 이동 함수
public class StartActivity extends FragmentActivity{
private static ViewPager2 mPager;
private FragmentStateAdapter pagerAdaoter;
//...
public static void fragmentChange(int index) {
if (index == 0) {
mPager.setCurrentItem(0);
}
else if (index == 2){
mPager.setCurrentItem(2);
} else if (index == 4){
mPager.setCurrentItem(4);
}
}
}
원래 Fragment간 통신 방법
나는 Bundle을 이용해서 내 방식대로 프래그먼트의 데이터를 받아왔지만, 원래 Fragment는 자신이 속한 activity와만 통신을 해야만 한다. 항상 자신이 속한 activity를 통해서 다른 fragment나 activity와 통신해야 한다는 말이다.
방법은 3가지 정도가 있다.
1. Bundle을 이용한 액티비티 전달
: Fragment생성 후, 데이터를 넣은 Bundle을 전달할 수 있다.
Fragment는 onActivityCreated메소드에서 번들을 받는다.
2. 메소드를 통해 Fragment의 메소드를 호출
3. Activity에서 리스터 이벤트 발생 : interface사용
참고로 프래그먼트는 Context클래스를 상속받지 않기 때문에 부모 액티비티를 얻기위해서 getActivity()를 사용
참고 링크
처음에는 프래그먼트의 onSaveInstanceState(Bundle outState) 에서 번들작업을 해주었는데, 액티비티가 종료될 때 여러 프래그먼트의 onSaveInstanceState 호출이 계속 뒤죽박죽이어서 번들에 제대로 데이터가 들어가지 않은 채 종료되었다.
생명주기를 계속 공부하다가 onStop에서 번들작업을 해주니 데이터가 제대로 들어가게 되었다.
프래그먼트의 사용에 관해: https://webnautes.tistory.com/1089
프래그먼트와 액티비티의 생명주기: https://jinee0717.tistory.com/44
https://ddangeun.tistory.com/50
'Android > Project' 카테고리의 다른 글
[Cafe In] 기록 #2: Retrofit2 (0) | 2022.03.02 |
---|---|
[Cafe In] 기록 #1 (0) | 2022.02.17 |
Spinner & DatePicker 사용해 시간/날짜 입력받기 (0) | 2021.08.05 |
ViewPager2 로 여러 개의 뷰 슬라이드 구현 (0) | 2021.08.04 |
RecyclerView사용 (0) | 2021.08.04 |