- 프레그먼트
- 프레그먼트 생명주기
1) 액티비티의 생명주기와 비슷하나, 그 주체를 관리하는것은 OS가 아니라 액티비티임.
2) 생명주기 : onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach
3) 프레그먼트의 다른 생명주기 메서드들은 public이어야 한다. 이유는 프레그먼트를 호스팅하는 어떤 액티비티에서도 호출될 것이기 때문이다.
- UI 프래그먼트의 호스팅
- 호스팅의 두 가지 방법
2) 프래그먼트를 액티비티의 코드에 동적으로 추가 - 권장
2. 주의 사항
1) 액티비티와 다르게 onCreate에서 프레그먼트의 뷰를 인플레이트하지 않는다. onCreateView에서 생성하고 구성
2) onCreate에서는 인스턴스화만 진행
3) 한 화면에 최대 2~3개 이하의 프래그먼트 사용을 권장
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_crime, container, false);
return v;}
View v = inflater.inflate(R.layout.fragment_crime, container, false);
return v;}
1) 프래그먼트를 관리하고 그것의 뷰를 액티비티의 뷰 계층에 추가하는 책임을 가짐.
2) 프래그먼트 리스트와 프래그먼트 트랜잭션의 Back 스택을 처리한다.
3) 프래그먼트 트랜잭션 : 프래그먼트 리스트에 프래그먼트를 추가, 삭제, 첨부, 분리, 변경하는데 사용, (런타임시에 화면을 구성 또는 재구성)
4) beginTransaction() 메서드는 프레그먼트 트랜잭션 인스턴스를 생성하여 반환.
- 프래그먼트 사용
- 서포트 라이브러리 그래들 추가
- 최신 메이져 버전 사용 권장
- 프래그먼트 인자를 활용하는 방법(Bundle 사용)
- Bundle : 인텐트 엑스트라와 동일하게 키와 값이 한 쌍으로 된 데이터
- 번들 객체를 생성 후 프레그먼트에 첨부한다. 단, 프레그먼트가 생성된 후에, 그리고 그 프레그먼트가 액티비티에 추가되기 전에 프레그먼트에 첨부해야 한다.
- 프래그먼트 생성자 대신, newInstance() 스태틱 메서드를 사용하는 것이 좋다.
- 호스팅 액티비티는 자신들의 프래그먼트들을 호스팅하는 방법을 자세히 알아야한다. 반면에 프레그먼트들은 호스팅 액티비티를 자세히 알 필요가 없다.
- 인자 가져오기
getArguments()를 호출한 후 타입별로 Bundle의 get~ 메서드를 호출.
public static CrimeFragment newInstance(UUID crimeId){
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_CRIME_ID, crimeId);
CrimeFragment fragment = new CrimeFragment();
fragment.setArguments(bundle);
return fragment;
}
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_CRIME_ID, crimeId);
CrimeFragment fragment = new CrimeFragment();
fragment.setArguments(bundle);
return fragment;
}
@Overridepublic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID crimeId = (UUID) getArguments().getSerializable(ARG_CRIME_ID);
mCrime = CrimeLab.getInstance(getActivity()).getCrime(crimeId);
}
- 호스팅 액티비티 코드
public class CrimeActivity extends SingleFragmentActivity {
private static final String TAG = "CrimeActivity";
private static final String EXTRA_CRIME_ID = "crime_id";
@Override
@Override
protected Fragment createFragment() {
UUID crimeId = (UUID) getIntent()
.getSerializableExtra(CrimeActivity.EXTRA_CRIME_ID);
return CrimeFragment.newInstance(crimeId);
}
public abstract class SingleFragmentActivity extends AppCompatActivity { protected abstract Fragment createFragment(); @LayoutRes
protected int getLayoutResId() { return R.layout.activity_fragment;
} @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(getLayoutResId()); FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container); if (fragment == null) { fragment = createFragment();
fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit();
} } }
* 리스트 -> 디테일 (데이터 변경) -> 리스트
- 리스트로 돌아오기 위해 사용자의 back 버튼 클릭시 리스트 액티비티가 started, resumed 된다.
- 액티비티 onResume() -> 프레그먼트들의 onResume() 호출
- 따라서 디테일 데이터 변경 뒤, 그 내용을 리스트에 반영 시키려면 fragment의 onResume()을 오버라이드하여 업데이트 해야함
- 생성된 어댑터가 있다면, adapter.notifyDataSetChanged() 호출. 하지만, 한 건의 수정을 위해 리스트 전체를 refresh하는 건 비효율적이므로, notifyItemChanged(int)를 사용한다.
- RecyclerView의 데이터를 변경하기 위해 어째서 onStart()가 아닌 onResume을 오버라이드 하는 것일까?
댓글
댓글 쓰기