원문 : http://developer.android.com/resources/articles/faster-screen-orientation-change.html
원문 : http://android-developers.blogspot.kr/2009/02/faster-screen-orientation-change.html
번역 : 이상훈 (calm1979@gmail.com)
2010년 6월 22일
안드로이드는 다양한 하드웨어 기반의 많은 기기들에서 효율적으로 동작하도록 설계되었다. T모바일 G1 처럼 몇몇의 기기에서는 동작 중에 하드웨어 설정을 바꿀 수도 있다. 예를 들어, 키보드를 열면 화면이 세로방향(portrait)에서 가로방향(landscape)으로 회전한다.
안드로이드 앱 개발자의 편의를 위해, 안드로이드 시스템은 설정이 바뀐 이벤트(configuration change events)를 자동으로 처리해주고, 새로운 설정에 맞게 현재 액티비티를 재시작 해준다. 이런 기본 동작 방식은 개발자가 기기의 방향, 화면 크기, 로케일 등에 기반한 레이아웃(layouts)이나 드로우어블(drawables) 같은 리소스들을 선언하도록 해준다.
이러한 동작 방식은 어플리케이션이 기기의 설정에 자동적으로 반응할 수 있게해주는 정말 강력한 것이지만, 액티비티가 왜 사라졌다가(destroyed) 다시 생성되어야하는지(recreated) 궁금해하는 개발자들을 헷갈리게 할 수도 있다.
대게 이런 "문제"에 직면하게되면, 일부 개발자들은 스스로 설정 변화에 맞는 처리를 하고자 한다. 그렇지만 이런 해결 방법은 단기적인 것이며 나중에는 오히려 상황을 더 복잡하게 할뿐이다. 반면에, 시스템이 자동적으로 리소스를 처리하는 것은 매우 효율적이며 어플리케이션의 UI가 다양한 기기와 환경에 대응할 수 있는 쉬운 방법이라고 볼 수 있다. 하지만, 이 것도 때로는처리하는데 비용이 들기도 한다.
어플리케이션이 대량의 데이터를 표시하거나, 데이터를 얻는데 드는 비용이 큰 경우, 액티비티를 자동적으로 죽이고(destruction)/살리는(creation) 것이 UX에 악영향을 끼칠 수도 있다. 간단한 플리커 탐색 어플리케이션인 포토스트림을 예로 보자. 어플리케이션을 실행한 뒤 플리커 계정을 선택하면 플리커 서버로 부터 6장의 사진(T모바일 G1의 경우임)을 다운로드하고 화면에 표시해준다. UX를 좋게하기 위해 어플리케이션은 세로 모드와 가로 모드별로 약간 다른 레이아웃과 드로우어블을 사용했다. 결과는 다음처럼 보여진다:
포토스트림은 화면이 회전되면 안드로이드 자체적으로 설정 변화에 맞는 처리를 하도록 했다. 그러나, 화면이 회전되었다고해서 사용자로 하여금 사진을 보기위해 모든 사진이 다시 다운로드 되어져야한다는 것이 얼마나 괴로운 일이겠는가? 이런 문제를 확실하게 해결하는 방법은 이미지를 임시로 저장해두는 것이다. 임시 저장 공간은 SD카드(장착되어 있다면)가 될 수도 있고, 어플리케이션 오브젝트 안에 스태틱 필드(static field) 같은 것으로 둘 수도 있다. 이런 방법 중에 현재 상황에 맞는 것은 하나도 없다: 화면이 회전되지 않을 때도 임시로 이미지를 저장하는 것에 신경쓸 필요가 있을까? 다행히도 안드로이드는 이런 상황에 딱 맞는 훌륭한 API를 제공한다.
액티비티 클래스는 onRetainNonConfigurationInstance()라는 특별한 메소드를 가지고 있다. 이 메소드로 미래의 자신(새로 만들어질 액티비티)에게 임의의 객체를 전달할 수 있고, 안드로이드는 필요할 때만 이 메소드가 불릴 수 있도록 잘 만들어져있다. 포토스트림 같은 경우에, 어플리케이션은 이 메소드를 사용해서 화면이 회전될 경우 미리 받아두었던 이미지들을 미래의 액티비티(새로 만들어질 액티비티)에게 전달하도록 했다. 구현 부분을 간단히 정리하면 다음과 같다:
@Override public Object onRetainNonConfigurationInstance() { final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos]; keepPhotos(list); return list; }
새로운 액티비티의 onCreate() 메소드에서는, getLastNonConfigurationInstance() 메소드를 호출해서 이전에 저장해두었던 객체를 돌려받아야 한다. 포토스트림 예에서는, 이 메소드를 호출해서 리턴값이 null이 아니면, 이전 액티비티에서 전달해준 이미지 목록을 사용하도록 했다:
private void loadPhotos() { final Object data = getLastNonConfigurationInstance(); // The activity is starting for the first time, load the photos from Flickr if (data == null) { mTask = new GetPhotoListTask().execute(mCurrentPage); } else { // The activity was destroyed/created automatically, populate the grid // of photos with the images loaded by the previous activity final LoadedPhoto[] photos = (LoadedPhoto[]) data; for (LoadedPhoto photo : photos) { addPhoto(photo); } } }
하지만, onRetainNonConfigurationChange() 메소드를 사용해서 객체를 전달할 때에는 매우 조심해야 한다. 전달하고자 하는 객체가 액티비티나 컨텍스트와 관련된 경우, 임의의 이유로 액티비티의 모든 뷰나 리소스들이 날아가버릴 수도 있다. 이것은 뷰(View), 드로우어블(Drawable), 어댑터(Adapter) 같은 것을 절대로 전달하지 않아야 한다는 뜻이다. 포토스트림에서는 이미지 전달을 위해 드로우어블이 아닌 비트맵 자체를 사용했다. 마지막으로, onRetainNonConfigurationChange() 메소드는 데이터를 얻는데 비용이 많이 드는 경우에만 사용할 것을 기억하길 바란다. 그게 아니라면 안드로이드가 알아서 처리할 수 있게 내버려두도록 하자.
'iOS & Android' 카테고리의 다른 글
Using WebViews (2) | 2010.06.30 |
---|---|
아이폰에서 안드로이드 구동하기 - Open iBoot (1) | 2010.05.07 |
안드로이드 에뮬레이터에 apk 설치 (0) | 2010.04.29 |