Skip to content

Application ShoppingApp

Devrath edited this page Jul 11, 2021 · 21 revisions
Contents-and-observations
Wrapping the live data in the Util Event class
Declaring live data observable in view model
Creating a Fake repository

Wrapping the live data in the Util Event class

Declaring live data observable in the view model

  • When we are creating an observable source like live data or flow we need to give the ability to modify the live data by the components inside the ViewModel. Then expose a variable for outside so it can be observed.
  • Thus mutable state is for the view model since only the view model should modify it, thus it's private.
  • We just expose the Live data since it just can be observed and not be modified and has no mutable state, thus it's public.

Declare in viewmodel

private val _images = MutableLiveData<Event<Resource<ImageResponse>>>()
val images: LiveData<Event<Resource<ImageResponse>>> = _images

Set the data in viewmodel

images.value = // set the state

Observe the live data from outside the view model, like activity or fragment

viewModel.images.observe(viewLifecycleOwner, Observer {

Creating a Fake repository

  1. We create a fake repository when we can swap between a real repository and a fake repository depending on our usage.
  2. We use a real repository when we are running our production code.
  3. We use a fake repository when we are testing our test cases.
  4. We inject the interface of the repository in the view model constructor.
  5. Now we need to create classes of the repositories (real repository, fake repository) that implements the interface which we inject into the view model.
  6. We. create the instance of the class that implements the interface using the hilt provides a method using a dagger

Define the interface

ShoppingRepository.kt -> This is useful in swapping the implementation for both the production and test cases of repository implementation

interface ShoppingRepository {
    suspend fun insertShoppingItem(shoppingItem: ShoppingItem)
    suspend fun deleteShoppingItem(shoppingItem: ShoppingItem)
    fun observeAllShoppingItems(): LiveData<List<ShoppingItem>>
    fun observeTotalPrice(): LiveData<Float>
    suspend fun searchForImage(imageQuery: String): Resource<ImageResponse>
}

DefaultShoppingRepository.kt -> This can be used in production code

class DefaultShoppingRepository @Inject constructor(
    private val shoppingDao: ShoppingDao,
    private val pixabayAPI: PixabayAPI
) : ShoppingRepository {
    override suspend fun insertShoppingItem(shoppingItem: ShoppingItem) {}
    override suspend fun deleteShoppingItem(shoppingItem: ShoppingItem) {}
    override fun observeAllShoppingItems(): LiveData<List<ShoppingItem>> {}
    override fun observeTotalPrice(): LiveData<Float> {}
    override suspend fun searchForImage(imageQuery: String): Resource<ImageResponse> {}
}

FakeShoppingRepository.kt -> This can be used in testing unit tests

class FakeShoppingRepository @Inject constructor(
    private val shoppingDao: ShoppingDao,
    private val pixabayAPI: PixabayAPI
) : ShoppingRepository {
    override suspend fun insertShoppingItem(shoppingItem: ShoppingItem) {}
    override suspend fun deleteShoppingItem(shoppingItem: ShoppingItem) {}
    override fun observeAllShoppingItems(): LiveData<List<ShoppingItem>> {}
    override fun observeTotalPrice(): LiveData<Float> {}
    override suspend fun searchForImage(imageQuery: String): Resource<ImageResponse> {}
}

AppModule.kt -> Here we will cast the interface to the repository making it return the repository, by doing so we can inject the interface and use the overridden methods used in repository

@Module
@InstallIn(ApplicationComponent::class)
object AppModule {
    @Singleton
    @Provides
    fun provideDefaultShoppingRepository(
        dao: ShoppingDao,
        api: PixabayAPI
    ) = DefaultShoppingRepository(dao, api) as ShoppingRepository
}

Clone this wiki locally