5~6월은 안드로이드 '기초'에 대해서 알아보았습니다.

안드로이드 프래그먼트(Fragment)

  • 5~6월은 안드로이드의 프래그먼트를 사용해서 가볍게 토이 프로그램을 만들어보는 것을 스터디하고, 몇가지 기초적인 사항을 기록으로 남겨봅니다.

  • 스터디를 하면서 배웠거나 알아봤던 내용을 기록으로 남기지 않아서 많은 내용은 없지만 필요한 몇가지 내용을 정리하였습니다.

  • 이런게 있구나... 하고 가볍게 읽어보시길 권해드립니다.

액티비티

  • 액티비티는 사용자와의 인터페이스를 구성하지만 그 자체는 출력 기능이 없어 직접적으로 보이지 않으며, 사용자 눈에 실제로 보이는 것인 뷰이며 그래서 액티비티는 반드시 내부에 뷰나 뷰그룹을 가져야 함 1
  • 화면의 기본 단위가 되고 가장 많이 쓰이는 컴포넌트이고 독립적인 화면이라면 액티비티를 고려하고, 종속적인 화면이라면 다른 컴포넌트를 사용 3
    • setContentView()를 반드시 호출해야 하는 것이 아님 해당 사항에 대한 내용은 레퍼런스 3을 참고할 것

액티비티 생명주기

  • 다른 액티비티가 일부만 가리면 onPuse(), 전체를 가리면 onSteop()을 호출하며, 종료시 전자의 경우 onResume을 후자의 경우 onRestartonStart()를 호출
    • 해당 내용의 세부적인 사항은 레퍼런스 3을 참고
  • 우선순위가 더 높은 앱이 메모리가 필요하다면 앱은 언제든 종료될 수 있기 때문에 onStop(), onDestroy() 메서드를 반드시 실행된다는 보장은 없음
  • 시스템에 의해서도 액티비티가 제거될 수 있기 떄문에 태스크의 목록이 유지된다고 가정하면 안 됨

액티비티 시작

  • 액티비티끼리 서로 호출하려면 통신을 위한 장치가 필요한데 이 장치가 바로 인텐트(Intent)1
    • Intent에 관한 세부적인 내용은 레퍼런스 1을 참고
  • startActivity()Context 메서드이기 때문에 어디서든 호출 가능하지만, startActivityForResult()Activity의 메서드임3

주의사항

  • onCreate()에서 생성했다면 onDestroy()에서 제거, onResume()에서 생성했다면 onPause()에서 제거
  • onCreate(), onStart(), onResume()에서는 super.onXXX가 먼저 실행되고, 나머지는 나중에 실행됨

구성변경

  • 구성(Configuration)은 컴포넌트에서 어떤 리소스를 사용할지 결정하는 조건, 이 조건 항목은 프레임워크에 결정되어 있음
  • 구성이 변경되어 액티비티를 재시작하면 하나의 인스턴스를 가지고 새로 초기화해서 재사용하는 것이 아니고, onDestroy()까지 실행하고 새인스턴스가 onCreate()부터 실행
  • 구성이 변경되어 재시작되어도 사용자 경험상 기존에 보던 화면을 유지하기 위해서 onRestoreInstanceState()onSaveinstanceState()를 사용하면 됨
    • onSaveInstanceState() 메서더는 targetSdkVersion에 따라 호출되는 시점이 다름

프래그먼트

            << 폰 >>                          << 태블릿 >>
--------------      --------------     ---------------------------
|            |      |            |     |            |            |
|            |      |            |     |            |            |
|            |      |            |     |            |            |
|   리스트   | -->  |   디테일   |  ,  |   리스트   |   디테일   |
|            |      |            |     |            |            |
|            |      |            |     |            |            |
|            |      |            |     |            |            |
--------------      --------------     ---------------------------

프래그먼트의 필요성

  • 태블릿은 핸드셋에 비해서 화면이 훨씬 넓어 화면에 더(핸드폰에 비해서) 많은 정보를 한눈에 볼 수 있기 있음
  • 액티비티는 화면 하나를 정적으로 정의하면 더 이상 분할하기 어려기 때문에 태블릿 전용으로 만들지 않으면 대화면의 이점을 누리지 못함
  • 액티비티보다 더 작은 화면 단위를 정의한 것이 프래그먼트, 프래그먼트를 조합하여 완성된 화면을 표현 액티비티에 비해 실행 중에도 추가, 제거, 교체 가능하여 동적이고 유연한 화면을 만들 수 있지만, 혼자서는 독립적으로 실행할 수 없음

프래그먼트의 주요 특징

  • 액티비티를 분할하여 화면의 한 부분을 정의
  • 자신만의 레이아웃, 독작, 생명주기를 가지는 독립적인 모듈
  • 여러 액티비티에서 재사용 가능
  • 실행 중에 추가, 제거, 대체 가능하며 잠시 숨길 수도 있음

프래그먼트 생성

  • 프래그먼트는 XML 레이아웃 파일의 저장형태로 추가될 수 있으며, 클래스 내부에서 직접 코드로 정의해서 사용할 수 있음
  • 프래그먼트를 사용하는 레이아웃의 경우 android.support.v7.app.AppCompatActivityandroid.support.v4.app.Fragment를 사용해야 하며 onCreateView()를 오버라이딩 해야함
  • XML 레이아웃 파일에 포함시킬 때는 <fragment>요소를 사용해서 액티비티 레이아웃에 포함

프래그먼트 생명주기

  • 많은 콜백 중에서 onCreate(), onCrateView(), onPause() 콜백은 거의 필수적으로 구현해야 하며 나머지는 필요할 때만 구현하면 됨
-----------------
|프래그먼트 추가|
-----------------
        |
--------v--------
|    onAttach   |
-----------------
        |
--------v--------     -----------------      -----------------
|    onCreate   | <-- | onDestroyView |  --> |   onDestroy   |
-----------------     --------^--------      -----------------
        |                     |                      |
--------v--------     -----------------      --------v--------
| onCreateView  |     |    onStop     |      |   onDetach    |
-----------------     --------^--------      -----------------
        |                     |                      |
--------v--------     -----------------      --------v--------
|   onStart     |     |   onPause     |      |프래그먼트 파괴|
-----------------     --------^--------      -----------------
        |                     |
--------v--------     -----------------
|   onResume    |     |프래그먼트 실행|
-----------------     -----------------

프래그먼트 초기화

  • void onAttach(Activity activity)

    • 프래그먼트가 처음 부착될 때 호출
    • 인수로 전달되는 activity는 프래그먼트가 배치되는 호스트 액티비티
      • 프래그먼트는 홀로 사용될 수 없고 항상 액티비티에 종속적으로 사용해야 함
  • void onCreate(Bundle savedlnstanceState)

    • 프래그먼트가 생성될 때 호출
    • 이 단계에서는 호스트 액티비티도 아직 초기화중인 상태이며 따라서 액티비티의 컨트롤을 안전하게 참조할 수 없기 때문에 완전히 초기화된 시점이 필요하면 onActivityCreated 콜백을 사용해야 함
    • savedlnstanceState는 프래그먼트가 재생성될 때의 이전 상태이며 이 값을 참조하여 이전 상태로 복구
  • View onCreateView(Layoutlnflater inflater, ViewGroup container, Bundle savedlnstanceState)

    • 프래그먼트 UI를 처음 그릴 때 호출되며 이 단계에서 프래그먼트는 자신의 레이아웃을 생성한 후 최상단(root) 뷰를 반환
    • inflater가 인수로 전달되기 때문에 inflater를 따로 생성하지 않아도 됨
      • inflate 메서드의 마지막 인수는 false여야 하고, 이 값을 true로 지정하면 전개된 뷰를 container에 부착해도 별다른 이상은 없으며 에러도 발생하지 않지만 이중으로 부착되어 자원만 낭비되므로 시스템에 맡겨두면 됨
    • container는 프래그먼트가 배치될 액티비티의 최상단 뷰이며 이 위치에 프래그먼트가 생성 및 배치됨

    @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_layout, container, false); }

  • void onActivityCreated(Bundle savedlnstanceState)

    • 액티비티가 완전히 초기화되고 프래그먼트의 레이아웃도 완성되었을 때 호출
    • 이 메서드에서 뷰의 상태를 복구하는 등의 동작을 안전하게 수행할 수 있으며 액티비티의 다른 위젯을 참조하거나 조작할 수 있음

프래그먼트 시작

프래그먼트 초기화의 메서드를 차례대로 실행 한 후 onStartonResume가 연이어 호출됨

  • void onPause()

    • 프래그먼트가 정지될 때 호출됨
  • void onSavelnstanceState(Bundle outState)

    • onPause와 함께 호출되며 이 메서드에서 임시 정보를 저장함
    • onState에 정보를 저장하면 프래그먼트가 재생성 될 때 다시 전달됨

프래그먼트 관리자

  • 프래그먼트와 관련된 편집 작업은 프래그먼트 관리자를 사용하며 이 객체는 아래 두 메서드로 구현

    • FragmentManager Activity.getFragmentManager()
    • FragmentManager Fragment.getFragmentManager()
  • 액티비티와 프래그먼트에 같은 이름의 메서드가 제공되므로 언제든지 관리자 객체를 얻을 수 있음

    • Fragment findFragmentByld(int id)
    • Fragment findFragmentByTag(String tag)
  • 프래그먼트는 다음 3가지 방식으로 지칭

    • id : 프래그먼트를 배치할 때 지정한 android:id 속성의 정수값을 사용
    • 부모의 id : 실행 중에 생성한 프래그먼트는 고유한 id가 없기 때문에 부모의 id를 통해 프래그먼트를 찾음
    • 문자열 형태의 태그 : 실행 중의 프래그먼트를 생성할 때 고유한 이름의 태그를 붙일 수 있으며, UI가 없는 프래그먼트의 겨우 XML 문서에서 android:tag 속성으로 태그명을 부여함

실행 중 프래그먼트 추가, 제거 교체

  • FragmentTransaction beginTransaction()

    • 동시에 여러 동작을 처리해야 하며 프래그먼트의 부피가 크면 상당한 시간이 걸릴 수 있음
    • 뿐만 아니라 각 동작마다 화면을 갱신하면 화면 깜박거림이 발생하기 떄문에 전체 편집 동작을 한 묶음으로 처리하기 위해 트랜잭션으로 처리함
    • 프래그먼트 관련 처리를 모아 두었다가 한꺼번에 처리하기 위해 트랜잭션으로 묶는 것 뿐임
  • FragmentTransaction add(int containerViewld , Fragment fragment [, String tag]), FragmentTransaction add(Fragment fragment , String tag)

    • 프래그먼트 추가를 위한 메서드
    • containerViewld는 프래그먼트가 추가될 부모 View의 id
    • fragment는 추가할 프래그먼트 객체이며, tag 인수로 이름을 지정
  • FragmentTransaction remove(Fragment fragment)

    • 프래그먼트가 화면에서 사라짐
  • FragmentTransaction replace(int containerViewld, Fragment fragment [, String tag])

    • 프래그먼트를 다른 프래그먼트로 대체
  • FragmentTransaction show(Fragment fragment), * FragmentTransaction hide(Fragment fragment)

    • 프래그먼트를 숨기거나 화면에 보일 수 있음
  • int commit()

    • 스레드가 한가할 때 처리하도록 스케줄링을 함
    • 이 메서드를 호출하지 안흐면 트랜잭션 편집은 모두 취소

  1. 김상형, "안드로이드 프로그래밍 정복 Vol.2 - 6.X 마시멜로와 안드로이드 스튜디오를 기반으로 다시 집필한, 전면개정판," 한빛미디어, 2016 (많은 분들이 참고하시는 교재이긴 하지만, 몇가지 변경사항이 반영되지 못한 부분이 존재하기 때문에 권하고 싶지 않음)

  2. 닐 스미스, 심재철, "실무에 바로 적용하는 안드로이드 프로그래밍," 제이펍, 2016 (부산에서 스터디를 하면서 가장 많은 도움이 되었음. 작은 프로젝트를 기반으로 진행되기 때문에 안드로이드 초심자분들에게 좋은 책)

  3. 노재춘, "안드로이드 프로그래밍 Next Step," 인사이트, 2017 (글을 작성하면서 참고한 책 중에서 가장 알찬 지식을 전해주는 책, 강추!)