Android 75

"좋아요" 동기화 (로컬 싱크 맞추기, Rx 이용)

- 상품상세 화면에서 좋아요를 하고 홈탭으로 돌아갔을때 이벤트 전파 - 마이페이지 탭에서 좋아요를 취소하고 홈탭으로 돌아갔을때 이벤트 전파 예전에 Rxbus와 같은 개념 1. 모델 생성 sealed interface WishEvent { data class AddWish( val id: Long ) : WishEvent data class RemoveWish( val id: Long ) : WishEvent } 2. 도메인 레이어 : 싱글톤으로 생성된 service에 구독할 Flowable함수와 값을 전달할 Processor 변수 추가 private val _event: FlowableProcessor = PublishProcessor.create() override fun fetchEvent(): F..

Android 2022.03.14

액티비티간, fragment간 값 전달 하기 (ViewModel X)

ViewModel 로 값 전달하면 서로 결속력이 너무 강해진다 리스너로 연결하는 방법도 있지만 그것보다 좀더 편한 방법이 있다. (리스너도 리스너객체를 전달하고 구현해야하기 하기때문에 불편) (Fragment or Activity) (Activity) private val productWishResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> if (result.resultCode == Activity.RESULT_OK) { viewModel.input.onRefresh() } } productWishResult.launch(ProductDetailActi..

Android 2022.02.12

쿠키로 Auth인증하는 방법 (Interceptor 첨부)

통신할때 Auth인증하는 방법중에 쿠키에 (헤더에) 인증값을 넣어 통신하는 방법 로그인또는 회원가입했을때 Response Header에 set-cookie 해당 키값을 찾아 value 를 저장해놓고 ( SharedPreferences ) Auth가 필요한 통신을 할때 저장된 value를 Request Header에 넣어 통신하는 방법 Retrofit Interceptor 첨부 internal class AuthInterceptor @Inject constructor( private val sessionProvider: SessionProvider ) : Interceptor { @Throws(IOException::class) override fun intercept(chain: Interceptor.C..

Android 2022.02.12

음성 파일 서버 업로드하기

음성파일 가져오기 개념 : 파일을 byteArray로 만들어 서버에 전송 하려고한다. - 당연하지만 만든다는건 변경한다는 의미가 아닌 copy의 의미 (단순히 읽는것임) 1. 파일로 만든다 File() : URI도 가능하고 경로String도 가능 2. InputStream에 넣는다 ( FileInputStream ) 3. 파일을 읽어서 byteArray형태로 가져온다 val fis = FileInputStream(File(speakingDirectory)) val byteArray = fil.readBytes() 코틀린 익스텐션 readBytes를 활용했는데 내부를 보면 Outstream도 만들어 주고, 알아서 처리해주니 너무 편리!! public fun InputStream.readBytes(): B..

Android 2022.01.10

DiffUtil 사용시 정렬후 스크롤 Top 으로 이동하기

Refresh -> 통신 -> 리스트 변경 -> DiffUtil 동작한 후에 스크롤 맨 위로 올리기 1. 뷰모델에서 통신을 성공하면 해당 LiveData를 동작 val requestScrollToTop : MutableLiveData = SingleLiveData() 2. 리스트가 변경됨 3. Activity에서 adapter에 registerAdapterDataObserver 리스너를 연결 requestScrollToTop.observe(lifecycleOwner) { productAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onItemRangeChanged(positionSta..

Android 2021.12.29

시간 간격 계산하여 x분전, x시간 전으로 변형하기

시간 계산하는건 익숙하지 않아서 기록용 fun Date.localizedTime(): String { val localDate = this.fromUTC() val nowMills = Instant.now().toEpochMilli() val createdMills = localDate.time val mills = nowMills - createdMills val minutes = mills / 1_000 / 60 val hours = minutes / 60 if (hours < 1) { return String.format("%d분 전", minutes) } if (hours < 24) { return String.format("%d시간 전", hours) } return localDate.forma..

Android 2021.12.24

API Response Map 형태로 받기 ( Retrofit )

API로 받은 필드 값이 고정 타입이 아니라면 어떻게 받아야 할까? "type": "event", "info": { "eventId": 613, "eventUrl": "https://string.com", "eventName": "ttttt", "eventType": "offline" } "type": "post", "info": { "postId": 12, "commentId": 1080, "postUserId": 2, "commentUserId": 781 } 서버에서 "info" 필드는 타입에 따라 다른 필드들을 받는다. 이런 경우 클라이언트에서는 info를 Map 형태로 받아서 처리하는 방법이다. @SerializedName("type") @Expose val type: String @Seriali..

Android 2021.10.04

리사이클러뷰 중첩 구조를 하나의 리사이클러뷰로 리팩토링 과정

아래와 같은 UI를 구현할때 어떻게 하는게 좋을까? 보통 기본적으로는 ScrollView 안에 TextView(헤더 내용), RecyclerView(이미지), TextView(하단 내용)으로 구성한다. 이렇게 하면 ScrollView의 세로 스크롤과 RecyclerView의 세로 스크롤이 겹치기 때문에 스크롤 이슈가 있을 수 있다. 또한 스크롤 뷰에 android:fillViewport="true" 속성을 넣게 되면 스크롤뷰가 content높이 계산을 하기 위해 RecyclerView가 모든 아이템을 그리게되는데 viewholder재사용을 하지 않아 RecyclerView의 이점을 얻을 수 없는 문제도 있다. 그래서 하나의 리사이클러뷰로 구조를 변경하는것이 좋다 ( ViewType 쪼개기 ) 상단 Tex..

Android 2021.09.29

카카오 로그인 Trouble Shooting

1. 카카오 로그인 해시코드 문제 : DEV, RELEASE 배포시 Firebase로 배포한 버전은 카카오톡 로그인이 정상, 스토어에 업로드한 버전은 로그인이 되지 않음 * 앱 업로드시의 인증서의 키해시가 아닌 플레이스토어용으로 변경되어진 인증서의 키해시를 넣어야함 ( 플레이스토어 콘솔 ) echo "${SHA-1 인증서 지문}" | xxd -r -p | openssl base64 이렇게 base64 인코딩하여 카카오톡 개발자콘솔에 넣음 (* 카카오는 스토어용 인증서의 키해시를 검사하는데 구글, 네이버는 업로드한 인증서의 키해시만 검사함 ) 2. loginWithKakaoAccount API 를 사용하여 로그인시 콜백 문제 문제 : loginWithKakaoAccount API로 웹뷰 화면을 띄우고 돌아..

Android 2021.09.29

어댑터 초기화후 데이터 넣기

통신을 하고 난후에 탭의 타이틀을 지정하거나 통신을 하고 난 후에 선택적으로 어댑터를 붙이는 경우가 있다. 이때 라이브데이터를 observe하고 난 후 ( 통신을 하고 난후)에 리사이클러뷰에 어댑터를 설정하지 않고 초기에 어댑터를 설정한 후에 나중에 데이터를 밀어주는 방식으로 변경하려고 한다. 리사이클러뷰 어댑터에서 해당 변수를 멤버변수로 지정 var type: QuestionType? = null set(value) { field = value notifyDataSetChanged() } override fun getItemCount(): Int = if (type == null) 0 else NUM_PAGES showEntry.observe { (entry, size) -> (viewDataBindi..

Android 2021.09.10