solobaba / flower

Flower simplifies networking and database caching on Android.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Flower is an Android library that makes networking and database caching easy. It enables developers to fetch network resources and use them as is OR combine them with local database at single place with fault tolerant architecture.

release contributors

Why Flower?

  • It helps you to handle different states (Loading, Success, Error) of resources efficiently.
  • It helps you to use local data in case of network unavailability.
  • It provides a fluid app experience by not blocking the main thread when accessing network/database resources.

You can find companion medium article here

Installation

Add Gradle dependency as below

dependencies {
    implementation("io.github.hadiyarajesh:flower:2.0.3")
}

Usage

Let's say you have a model class MyModel which you are fetching from network

data class MyModel(
    val id: Long,
    val data: String
)

Prerequisite

  • Return type of Room DAO function must be Flow<MyModel> (Only if you're caching network resources using a local database)
@Dao
interface MyDao {
    @Query("SELECT * FROM Data")
    fun getLocalData(): Flow<MyModel>
}
  • Return type of Retrofit api interface function must be Flow<ApiResponse<MyModel>>
interface MyApi {
    fun getRemoteData(): Flow<ApiResponse<MyModel>>
}



1. Add FlowCallAdapterFactory as CallAdapterFactory in Retrofit builder

Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(okHttpClient)
    .addCallAdapterFactory(FlowCallAdapterFactory.create())
    .build()



2. In Repository

2.1. If you want to fetch netwrok resources and cache into local database, use networkBoundResource() higher order function. It takes following functions as parameters

  • fetchFromLocal - It fetch data from local database
  • shouldFetchFromRemote - It decide whether network request should be made or use local data
  • fetchFromRemote - It fetch data from network
  • processRemoteResponse - It process response of network request. (e.g., save response headers)
  • saveRemoteData - It saves result of network request (MyModel) to local database
  • onFetchFailed - It perform provided action when network request fails (e.g., Non HTTP 200..300 response, exceptions etc)
fun getMyData(): Flow<Resource<MyModel>> {
    return networkBoundResources(
        fetchFromLocal = { myDao.getLocalData() },
        shouldFetchFromRemote = { localData -> localData == null },
        fetchFromRemote = { myApi.getRemoteData() },
        processRemoteResponse = { },
        saveRemoteData = { myDao.saveMyData(it) },
        onFetchFailed { errorMessage, statusCode -> }
    ).flowOn(Dispatchers.IO)
}

OR

2.2 If you only want to fetch network resources, use networkResource() higher order function

fun getMyData(): Flow<Resource<MyModel>> {
    return networkResource(
        fetchFromRemote = { myApi.getRemoteData() },
        onFetchFailed { errorMessage, statusCode -> }
    ).flowOn(Dispatchers.IO)
}



3. In ViewModel
Collect/transform Flow to observe different state of resources (Loading, Success, Error)

sealed class UiState<out T> {
    object Empty : UiState<Nothing>()
    object Loading : UiState<Nothing>()
    data class Success<out T>(val data: T?) : UiState<T>()
    data class Error(val data: String?) : UiState<Nothing>()
}
private val _myData: MutableStateFlow<UiState<MyModel>> = MutableStateFlow(UiState.Empty)
val myData: StateFlow<UiState<MyModel>> = _myData

init {
    viewModelScope.launch {
        getMyData()
    }
}

suspend fun getMyData() = repository.getMyData().collect { response ->
    when (response.status) {
        Resource.Status.LOADING -> {
            _myData.value = UiState.Loading
        }
        Resource.Status.SUCCESS -> {
            _myData.value = UiState.Success(response.data)
        }
        Resource.Status.ERROR -> {
            _myData.value = UiState.Error(response.message)
        }
    }
}



4. In Activity/Fragment/Composable
Observe view model data in Activity/Fragment/Composable function to drive UI changes

lifecycleScope.launchWhenCreated {
        viewModel.myData.collect { data ->
            when (data) {
                is UiState.Loading -> {
                    // Show loading
                }
                is UiState.Success -> {
                    // Show success
                }
                is UiState.Error -> {
                    // Show error
                }
                else -> { }

            }
        }
}

Sample

Sample app is provided in this repository. It fetch random quote from remote api and save it to local persistent database in order to display it on UI.

License

MIT License

About

Flower simplifies networking and database caching on Android.

License:MIT License


Languages

Language:Kotlin 100.0%