리사이클러뷰를 사용할 때 성능향상을 위해 DiffUtil을 이용할 것이다. 그런데, DiffUtil을 사용하면서 주의해야할 중의 하나는 ArrayList나 var 멤버가 포함된 mutable한 데이터 타입을 사용하는 것이다. 결론적으로 말하면, 이런 데이터 타입을 사용할 경우 데이터를 변경했음 해도 불구하고 리사이클러뷰가 업데이트 되지 않게 되는 현상에 직면하게 된다. 관련 코드를 통해 해당 증상을 살펴보자. 아래와 같이 ListAdapter를 이용해 사용자를 추가하는 간단한 앱이 있다. Add를 누르면 사용자를 리사이클러뷰에 추가할 것이다. 레이아웃과 관련코드이다. class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanc..
Android SDK introduced Result API recently and it looks better than just passing target fragment and get the result in onActivityResult. onActivityResult sounds bit weird when we receive the result from a Fragment. This API works with Fragments and we can use it for DialogFragment as well because DialogFragment is also Fragment. We need to register listener to FragmentManager to observe from a F..
We have use cases when we have to pass String message from ViewModel to View often. In Android, the system support String resources and it would be nice to use String resource instead of hard coded strings whenever possible. You might have had some situations you need to pass String resources from your ViewModel to activity or fragment but you don't want to pass Context to your ViewModel. You mi..
Kotlin사용자라면 Sythetic pulgin이 deprecated되고 ViewBinding(구글의 권장사항)으로 마이그레이션 해야된다는 걸 알고 있을 것이다. 그런데 ViewBinding을 프레그먼트에서 사용하게 될 경우 Memory leak과 관련된 이슈가 있는 것도 아마 알 것이다. (구글 문서에 나와있으므로) 아래는 개발자 문서의 샘플코드이다.(https://developer.android.com/topic/libraries/view-binding) private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val b..
실제 업무를 하다보면, Build flavour와 Build type에 따라 각각 다른 endpoint에 접속할 경우가 많다. 예를 들면, 개발시에는 개발서버나 테스트 서버에 있는 API를 사용을 하고 릴리스 후에는 프로덕션에 있는 API를 사용할 필요가 생긴다. 또는 개발시에는 Base URL을 세팅에서 바꿀 수 있는 옵션을 제공할 때도 있다. 어떻게 하면 좀 더 깔끔하게 빌드환경에 따른 Base URl 관리를 할 수 있을까? 여러가지 다양한 구현 방법이 존재하겠지만, Bridge Pattern이 이런 경우에 적합할 것 같아 보인다. dev와 prod flavour가 있고, Dev, UAT, PROD 환경이 있다고 하자. 그렇다면 다음과 같은 형태로 클래스를 설계해 볼 수 있을 것이다. Flavour는..
Navigation Component를 사용하면서 접하게 되는 Usecase는 Splash Screen이다. 왜냐하면 Splash Screen은 앱이 실행될 때 제일 먼저 떴다가 사라져야 하고, 백스택에서 제거되어야 하기 때문이다. 네비게이션 그래프를 보자. 아래와 같이 두개의 SplashFragment와 MainFragment가 존재하고 SplashFragment가 시작 Fragment이다. 아래는 SplashFragment 클래스이다. 3초 후에 MainFragment로 이동한다. class SplashFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstance..
From the previous blog, how can we dismiss loadin spinner after data has been loaded. SectionLifecycle.dispatchLoadingEvent We can send loading event to GroupSection to stop loading. We can simple add one line of code to onDataLoaded(). HeroesComponent.dispatchLoadingEvent(c, false, LoadingEvent.LoadingState.SUCCEEDED, null) Your onDataLoaded() will look like following now. @OnEvent(HeroModel::c..
We are using static items for hero list. What do we do if I want to load data from a service. We are going to use same data but we will use data loader instead of hard coded data. Let's initialise hero data first. We need to provide @OnCreateInitialState annotate function to do this in HeroesComponentSpec. @GroupSectionSpec object HeroesComponentSpec { @OnCreateInitialState fun onCreateInitialSt..
We're going to display list of hero name, image and description on the screen. You can think I am gonna build RecyclerView using Litho. Let's define data class for hero first. data class Hero( val name: String, val description: String, @DrawableRes val image: Int)It's straightforward and let's prepare hero data. package com.mpark.android.marblecharacters class DataLoader { compan..
GroupSection Spec's Lifecylce looks like following: GroupSection Spect has lifecycle in order below: @OnCreateInitialState To set an initial value for a state, you have to write a method annotated with @OnCreateInitialState in your spec. The first parameter must be of type ComponentContext. StateValue and @Prop are allowed. For example, @LayoutSpec object CheckboxSpec { @OnCreateInitialState fun..