본문 바로가기

안드로이드 Android

안드로이드 개발 (21) 홀수 짝수, Release Key, Diff Utill 등등

안녕하세요 안드로이드 개발자 Loner입니다. 주말이 다가와서 잠시 사이드 프로젝트를 즐기고 있습니다. 사이드 프로젝트를 함께하는 삶은 개발자만이 가질 수 있는 큰 특권이 아닐까 싶네요 오늘도 경험했던 일을 소소하게 정리하는 글을 남기도록 하겠습니다.

 

1. 프로그래밍에서 홀수 짝수 찾는법

 

이상형 월드컵과 같이 라운드의 수가 짝수의 경우에만 동작해야하는 경우가 있습니다.

이 경우 간단하게 조건문으로 2의 나머지를 구하면 됩니다. 0이면 짝수이고 , 1이면 홀수 입니다.

 

예제 

       if (userMissions.size() % 2 == 1) {
                    userMissions.remove(userMissions.size() - 1);
                }

-  %2 == 1은 홀수인지 체크합니다.

- 반대로 %2 == 0 은 짝수인지 체크합니다. 

- 위 예제는 누구든지 사진을 올려서 게임에 직접 참가할 수 있는 토너먼트 식 이상형 월드컵을 구현중입니다. 그래서 만약 전체 참여자가 홀 수 일땐 전체 참여자수를 짝수로 맞추는 분기처리 입니다. 

 

2. ReleaseKey 언제든지 빠르게 구하는 법

 

소셜 로그인 관련해서 Release Key가 필요한 경우가 많습니다. 디버깅 Key 같은 경우 간단하게 안드로이드 스튜디오 우측 에 signingReport를 더블 클릭해서 빠르게 sha 1 키를 얻는 경우가 많습니다. 하지만 기본적으로 Relese Key의 경우 직접 명령어을 쳐야 확인 할 수 있습니다.

 

저는 귀차니즘이 있어서 더블클릭을 해서 빠르게 찾는걸 선호하는 편입니다. 처음에 터미널로 한번 릴리즈 키를 뽑고나면 확인해볼일이 없는줄 알앗는데  어쩌다 상황이 다시 릴리즈 키를 확인해야 하는 상황이 몇번 와서 아예 아래와 같이 셋팅 해놓고 Release Key를 signingReport로 빨리 찾습니다. 

 

주의 할점은 아래와 같은 셋팅은 언제나 제 스타일임으로.. 

차후에 문제가 있을 수 있습니다. 나중가서 반드시 원래 셋팅으로 돌려놓기를 권장합니다.

 

- SigningReport 로 릴리즈 키 확인하는법 -

 

안드로이드 좌측 하단에 Bulid Variants 라는 탭을 누르면 위같은 창이 뜹니다.

debug와 release를 선택할 수 있는데 release로 설정합니다.

 

그 다음 app 모듈을 오른쪽 클릭하면 open Module Settings가 나옵니다. 눌러줍시다. 

 

그럼 위 같은 화면이 나오는데 Signing Configs 탭을 눌러서 + 버튼을 눌러줍시다. 

누르면 name를 적으라고 뜨고 적고 싶은 Name 를 입력해주고 생성합시다. 

 

+를 눌러서 생성하면 위 같은 선택지들이 뜹니다. 

- Store File은 내가 해당 앱의 Apk를 만들때 서명 했던 .jks 파일을 선택하면 됩니다. 

- 선택했던 .jks 파일의 Password와 KeyAlias를 입력해줍시다.

- 다 적었으면 좌측 탭에 Bulid Variants 탭을 누르면 위같은 창이 뜹니다.

- Debuggable를 true로 바꿔주고 Signing Config를 설정해 줍니다.

 

자, 이제 셋팅 완료했으니 사용하면 됩니다.

안드로이드 우측에 Gradle 탭을 누릅시다. 

그 다음 signingReport를 찾아서 더블클릭하면 

이제 디버그 키가 아니라 릴리즈 키를 언제든지 signing Report를 눌러서 확인 할 수 있습니다. 

 

 

3. Diff Util 활용 

안드로이드 개발자는 거의 필수로 사용하는것이 바로 RecyclerView 입니다. 하지만 RecyclerView를 사용할 때 한번쯤 겪어봤을 고충은 바로 아이템 새로 추가했을 시 깜빡임 현상을 어떻게 제거 시키냐는 고민은 한번쯤 했을 것 입니다.

깜빡임 제거 방안으로 여러가지 방법이 있습니다.

 

대표적으로 notifyDataSetChanged() 대신에 notifyItemInserted() 를 사용하는 방법이 있습니다. 하지만 이런 방법들은 리스트가 매우 자주 변하는 상황일시 다른 상황에 따른 조건 처리가 들어가는 경우가 많기 때문에 차라리 Diff Util 로 심플하게 처리하는것도 나쁘지 않는 방법입니다.

 

Diff Util에 대한 자세한 설명은

https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil

 

DiffUtil  |  Android 개발자  |  Android Developers

DiffUtil public class DiffUtil extends Object java.lang.Object    ↳ androidx.recyclerview.widget.DiffUtil DiffUtil is a utility class that calculates the difference between two lists and outputs a list of update operations that converts the first list

developer.android.com

 

여기서 확인 할 수 있습니다. 

 

Diff Util의 기본 구현 방법은  아래 링크에서 참고하시길 바랍니다.

https://onemask514.tistory.com/48

 

[Android] RecyclerView DiffUtil

Intro 안드로이드에서 Recycler View와 Adpater는 거의 뭐 매번 사용됩니다. ReyclerView가 갖고 있는 item이 변하게 되면 notifyItemChanged로 알려줘야 하는데요 그런데 위 메소드가 불러지고 나면 adapter는 새..

onemask514.tistory.com

 

채팅방을 들어가기 전에 채팅 리스트 구현을 소켓 기반으로 하는중이라서 서버에 작은 변화라도 있을시 아이템이 살짝씩 바뀔때 전체 깜빡임 현상이 있어서 DiffUtil로 간단하게 해결했습니다. 하지만..

 

어떤 채팅방에 들어가서 뒤로가기를 눌러 채팅리스트로 돌아왔을 때 해당 채팅방이 깜빡이는 현상을 발견했습니다. 

원인을 분석한 결과 협업하는 동료가 채팅방을 나갈때 onStop()에서 해당 채팅방에 대한 db를 업데이트를 하는 구문을넣어놨었기 때문이었습니다. 

 

그렇다고 그 구문을 빼버리자니 또다른 난처한 상황이 올까봐 Diff Util의 특성으로 해결하기로 했습니다. 

 

변경 전 예제

   class DiffCallback : DiffUtil.ItemCallback<ChatList>() {
        override fun areItemsTheSame(oldItem: ChatList, newItem: ChatList): Boolean {
            return oldItem == newItem
        }
        
        ....

areItemsTheSame은 바꾸기전 아이템과 새로운 아이템을 비교합니다. areContentsTheSame와 달리 전체를 비교하기 때문에 db의 일부분이라도 바뀌어서 받게 된다면 바로 true를 반환해서 새로운 아이템으로 교체합니다. 

 

동료가 채팅방을 나갈때 onStop에서 db의 일부분을 바꾸는 업데이트를 했기 때문에 서버에서 db변경을 감지하고 클라이언트로 다시 데이터를 보낼때 전체 모델로 받기 때문에 사소한 변경이라도 있을 시 위 구문을 true로 받아서 채팅방을 나가는 순간 들어갔던 채팅방 아이템이 깜빡이는 현상이 있었던 것이었습니다.

 

변경 후 예제 

   class DiffCallback : DiffUtil.ItemCallback<ChatList>() {
        override fun areItemsTheSame(oldItem: ChatList, newItem: ChatList): Boolean {
            return oldItem.chatRoom.lastChatTimeStamp == newItem.chatRoom.lastChatTimeStamp
        }
        ...

그래서 전체 아이템을 보지 못하도록 

해당 필드가 변경시에만 아이템이 수정되도록 설정을 해놨습니다. 

 

DiffUtil의 편리함 덕분에 위 코드를 적용하고 아주 부드러운 UI처리가 가능하게 되었습니다.

이 포스팅에서는 Diff Util에 따른 사용을 어떻게 했었는지 제가 기록만 했습니다.

기본 사항은 위에 있는 예제 링크를 확인하세요 

 

4. FireBase RealTimeBase는 기본적으로 Array가 존재하지 않는다.

RealTimeBase로 작게 프로젝트를 하나 진행하고 있습니다. 어떤 테이블의 필드가 ArrayList<String> 였는데 서버 데이터에 테이블 필드에 ArrayList<String>에 element를 하나씩 추가를 해야하는 상황이었습니다. 하지만 RealTimeBase는 알고보니 Array를 정식적으로 지원하지 않아서 해당 필드를 Map으로 사용해야만 update기능을 공식적으로 사용할 수 있었습니다.

 

Array로 db에 insert는 할 수 있습니다. 그렇다면 서버에서 해당 Array를 가져와서 거기에 아이템을 하나 추가한뒤 다시 서버에 덮어씌우는 형식으로 사용해야할탠데 이러면 여러 유저가 동시에 insert를 하게 될때 문제가 되기 때문에 

개인앱을 만드는데 RealTimeBase 를 사용한다면 가능하면 Array대신 Map를 사용하기를 권장합니다.

 

혹은 RealTimeBase 말고, FireStore를 사용해도 됩니다. FireStore는 배열도 덮어씌우지 않고 1개씩 update를 할 수 있게끔 지원해줍니다.

 

5. 앱을 아름답게 하려면 앱 테마색깔을 잘 사용하자

오늘 진행한 사이드 프로젝트에서 ProgressBarFloating Action Button을 사용해야했습니다.

이 두개는 기본적으로 앱의 테마 색깔이 적용이 됩니다. 

 

머트리얼 디자인 가이드에 따라 이러한 아이콘들은 단색 Color를 중점으로

테마색깔을 사용하도록 권장하기 때문에 기본적으로 앱 전테 테마색이 적용되고 있는것 입니다.

 

그래서 특별한 경우를 제외하고 자동적으로 테마색이 사용되는 View들은 모두 임의로 색깔을 설정하지말고 테마 색을 미리 설정해놓은 뒤 해당 View가 자연스럽게 앱 스타일에 녹아들도록 하는것이 가장 편리하고 효과적인 작업 방식입니다.

 

 

1. 색감 적용전 

 

 

2) 색감 적용후

 

 

 

이상 오늘 건드려본 부분들을 다시 간단하게 정리해봤습니다.

대단한 내용은 없습니다만 이런 작은 경험들 하나하나가 쌓이는것이 개발의 묘미이지 않나 싶습니다.

개발은 역시 사랑이네요.