[안드로이드 공부]/프리퍼런스

안드로이드 오버라이드의 비밀과 함정 -Preference

코코모아 2015. 10. 8. 08:30

아래는 코모스튜디오가 직접 만든 무료 앱이에요
(한 번만 봐주세요 ^^)

01

02

03

정각알림 만들기(말하는시계)

말하는 시계 (취침, 자전거) 

말하는 타이머 음성 스톱워치 

PreferenceActivity의 기본 아이템들은 타이틀, 서머리 또는 체크박스만 있기 때문에 너무 단조롭다. 그래서 안드로이드는 오버라이드해서 내 맘대로 UI를 바꿀수 있도록 제공한다. 결국, 아래 그림처럼 seekbar를 넣어서 좀 더 다이나믹하고 인터랙티비한 형태로 바꿀 수 있다. 




방법은

1. Preference를 extends 하는 클래스를 하나 만든 다.

2. 새로 만든 클래스에서 반드시  onCreateView를 만들어 줘야한다.



위 처럼 onCreateView를 만든 뒤, inFlate할 레이아웃을 하나 가져와야 한다.

R.layout.seekbar_preference은 아래와 같이 만들면 된다.



3. 이제 다왔다. 마지막으로 PreferecneScreen 에서 기존에 사용했던 <Preference .... />를  <com.comostudio.preference.seekbarpreference ... />로 바꾸어 준 뒤 사용하면 된다.


이제 부터는 코드에서 setSummary를 사용하여 서머리를 마음대로 바꿀 수 있으며, seekar의 동적인 움직임도 바로 바로 적용되도록 만들 수 있다. 


4. SeekBar를 예로 들었으니 아래처럼 동적인 코드를 예로 들어보자... 이렇게 작성 하면 PreferenceActivity에 바로 적용될 수 있는 정보를 만들 수 있다.



5. 하지만, 여기서 주의 해야 할 것이 있는데 persistInt(newValue) 부분을 해주지 않으면, 다음 번에 액티비티에 다시 들어오면 값이 이전 값으로 무조건 초기화 되는 갑갑한 사태를 맞이 할 수 있다. 그럼 이게 끝이냐?



6. 위 메서드를 하나더 오버라이드 해줘야 한다. 여기에서 이전 값을 현재 바뀐 값으로 대체 해준다. 결국 안드로이드 소스에 가보면 알 수 있지만, 이런 과정을 거쳐야 보통 많이들 쓰는 save sharedpreference 같은 효과를 얻을 수 있게 되는 것이다. 일반 액티비티등에서 sharedpreference를 따로 만들어서 저장 해야 하지만 프리퍼런스 액티비티에서는 그럴 필요 없이 위와 같이 저장하면 된다.(물론 이것은 특이한 경우이고, 오버라이드를 하지 않는 다면 위의 1~5 모든 과정이 필요 없이 그냥 저장된다.) 저장된 값이 필요할 경우에는 어디에서든지  getDefaultSharedPreference만 호출 하면 저장되어있는 값을 가져 올 수 있다.


7. 자 여기 까지 왔다면 맨 처음 보여드렸던 그림이 나타났을 것이다. 하지만, 문제는 여기서 실수를 몇가지 하면 절대 서머리라든지 변경 하려고 했던 어떤 작업도 보여지지 않을 것이다.


8. 만약 1번에서 적용 했던

               mSummary = (TextView) mV.findViewById(android.R.id.summary);을 

               mSummary = (TextView) mV.findViewById(android.R.id.my_summary);로 수정 한다면?

즉, 기본 서버리를 쓰지 않고 내가 만든 TextView로 수정 한다면? 엄청난 재앙이 생긴다....


예를 들어,

상속받아 오버라이드해서 만든 SeekbarPreference에서 작업이 끝난 뒤..... 메인 프리퍼런스 액티비티로 넘어 온 뒤, mSummary.setText();로 값을 변경 하려 한다면... 절대 변경이 안되는 경우가 발생 할 수도 있다. Summary는 반드시 위 레이아웃에서 만들었던 android.R.id.summary 값을 반드시 써야 하며, 그렇지 않으면 절대 변경 되지 않는다. 만약, 이를 변경 하려면 preference 의 onBindView를 오버라이드 하여 새로운 작업을 더 추가 해주어야만 한다. 


그리고, 마지막으로 하나만 더...

만약... SeekbarPreference에서 asyncTask를 써서 다이얼로그가 닫힐 때 비동기 작업을 하고 있다면! callChangeListener()를 부르는 타이밍을 잘 조절 해야한다! 이 리스너를 부르면 프리퍼런스액티비티의 OnPreferenceChangeListener로 돌아간다. 이때 서머리등의 변경 작업을 해주면 되는데... 문제는 이 OnPreferencceChage가 닫히고 나면 다시 SeekbarPreference의 asyncTask로 돌아온다는 것이다. UI 작업이니 onPostExecute 메서드에서 callChangeListener()를 호출 했을 것인데... 그 뒤로 돌아 올 것이다.. 변경된 작업이 있다면 반드시 onPostExecute 메소드 맨 마지막에  callChangeListener()를 호출 하던지... 핸들러를 사용하여 몇 초 뒤에 callChangeListener() 호출 하던지... 다른 async 작업이 남아있는지 등을 반드시 확인 해야 한다. 


별 것 아닌 것 같지만 중요한 부분이다. onDialogClosed가 작동해도 asyncTask는 돌아가기 때문에 전역 변수를 사용한다면 정말 조심해야 한다. 엉뚱한 값들을 가져오거나.... 허공에다 숟가락을 들이 밀고 밥을 먹이는 일이 발생할 수도 있다...


안드로이드 개발 초보가... 이런 것을 하려니.... 머리가 아파온다.... 


모든 게시물은 코모스튜디오의 소유이며, 무단 복제 수정은 절대 불가입니다.
퍼가실 경우 댓글과 블로그 주소를 남기고 해당 게시물에 출처를 명확히 밝히세요.