Handy states for dynamically obtained data.

Overview

Release License

Resource

Handy states for dynamically obtained data.

Table of contents


Problem to solve

In contemporary software development a huge number of operations and their results are asynchronous. For instance, you're obtaining some data from remote server. Let's say, you're creating some kind of Observable and observe its value changes, which is initially null. Next you trigger some fetchRemoteData() and wait.

Five seconds have passed, but value is still null. What does it mean? Was there some error? Was the result null? Or connection is still being established, and you have nothing to worry about?

This is where Resource kicks in.

It represents some explicit state of dynamically obtained data. For instance, it could be Empty , Loading, Success or Failure state, where Success carries obtained data and Failure encapsulates exception cause and any useful payload, like error code.

Besides, Resource is a highly customizable state machine and may be used as a flexible tool for managing state.

Reasons to use

  1. Concept is easy to understand.
  2. Implementations of Resource are immutable, which makes them a great choice to use with such solutions like Kotlin Flow and Android LiveData.
  3. Has a lot out-of-the-box features implemented with Kotlin extension functions.
  4. Small source code size.
  5. 100% documented.

Artifacts

resource-plain

com.github.mmolosay.resource:resource-plain:VERSION

Sealed implementation of Resource with only Resource.Empty, Resource.Loading, Resource.Success and Resource.Failure derived states. Sealing makes it exhaustive in when statement, thus it's easy to cover all cases of actual instance. Note: author recommends to use Resource.invoke() extension function instead of when expression.

resource-context

com.github.mmolosay.resource:resource-context:VERSION

It is a preferred flavor of Resource library to use.

Philosophy of this flavor allows you to customize a context, in which your Resource states will change.

For example, you may want your resource to only have states of Empty and Success (ReducedScope), when you're interested in data or its absence only. You will be given scope, in which you can create states for resource: it will protect you from setting state out of context. Neat, isn't it? :>

See Example of usage section for more details.

Installation

Use JitPack to add it as a dependency to your Kotlin project. Code snippet below shows way for adding it via Gradle Kotlin DSL:

repositories {
    mavenCentral()
    maven("https://jitpack.io") // make sure to use jitpack repository
}

dependencies {
    implementation("com.github.mmolosay.resource:ARTIFACT:VERSION")
}

Where:

  • ARTIFACT is a desired implementation. See Artifacts section for more details.
  • VERSION is the version of desired release. It can be obtained on releases page. Latest release version is stated at the top of this document in JitPack badge.

Example of usage

Following simplified examples demonstrate a way to use Resource flavors with Kotlin Flows:

resource-plain

Full sample is in sample.resource-plain module.

// Declare your resource flow
val flow = MutableStateFlow(Resource.empty<YourData>())
...
// Change values
fun getData() {
    flow.update { Resource.loading() }
    try {
        getDataAsync { data ->
            flow.update { Resource.success(data) }
        }
    } catch (e: SomeException) {
        flow.update { Resource.failure(e) }
    }
}
...
// Observe changes
flow.collect { resource ->
    resource.invoke(
        onEmpty = { /* update UI, like showing some message */ },
        onLoading = { /* update UI, like showing progress bar */ },
        onSuccess = { data -> /* populate data to UI */ },
        onFailure = { payload, cause -> /* display notification on UI */ }
    )
}

resource-context

Full sample is in sample.resource-context module.

// Declare your resource flow
val flow = MutableStateFlow(resource<YourData>()) // empty by default
...
// Change values
fun getData() {
    flow.update { it with { loading() } }
    try {
        getDataAsync { data ->
            flow.update { it with { success(data) } }
        }
    } catch (e: SomeException) {
        flow.update { it with { failure(e) } }
    }
}
...
// Observe changes
flow.collect { resource ->
    // You can use provided extension or write your own for your custom states
    resource.invoke(
        onEmpty = { /* update UI, like showing some message */ },
        onLoading = { /* update UI, like showing progress bar */ },
        onSuccess = { data -> /* populate data to UI */ },
        onFailure = { payload, cause -> /* display notification on UI */ }
    )
}

License

Copyright 2022 Mikhail Malasai

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
A music player UI am designing in Jetpack Compose. The data is being fetched from Deezer's API.
A music player UI am designing in Jetpack Compose. The data is being fetched from Deezer's API.

Jetpack-Compose-MusicPlayer-UI 🎵 - Still under development This is a small project I am doing to interact with and explore Jetpack Compose components

Clean MVVM with eliminating the usage of context from view models by introducing hilt for DI and sealed classes for displaying Errors in views using shared flows (one time event), and Stateflow for data

Clean ViewModel with Sealed Classes Following are the purposes of this repo Showing how you can remove the need of context in ViewModels. I. By using

Course_modularizing_android_apps - Multi-module demo app that gets data from a Dota2 api
Course_modularizing_android_apps - Multi-module demo app that gets data from a Dota2 api

Work in progress Multi-module demo app that gets data from a Dota2 api. Module n

Location-history-viewer - Small compose-desktop app to view data from google's location history

Google Location History Takeout Viewer This application provides a minimalistic

AppConversorMoedas - The currency conversion using an API to bring the data up to date
AppConversorMoedas - The currency conversion using an API to bring the data up to date

LAB - Criando um app de conversor moedas/cambio com Kotlin. O curso pode ser ace

ViewModel LiveData Sample - Sample of using ViewModel, LiveData and Data Binding

ViewModel_LiveData_Sample Sample Code for Lesson 8 using ViewModel, LiveData and

Project-applocker - A concept app that uses Jetpack Security to encrypt user data such as text files or images using Encrypted Shared Preferences
Recycler-coroutines - RecyclerView Auto Add Data Using Coroutines

Sample RecyclerView Auto Add With Coroutine Colaborator Very open to anyone, I'l

Filmesflix - Project made during the NTT DATA Android Developer bootcamp. Developing knowledge in MVVM and Clear Architecture
Filmesflix - Project made during the NTT DATA Android Developer bootcamp. Developing knowledge in MVVM and Clear Architecture

FilmesFlix Projeto criado para o módulo de MVVM e Clean Architecture no Bootcamp

Releases(1.2.0)
Owner
Misha Malasai
Passionate developer and aspiring software architect
Misha Malasai
:speedboat: Floating navigation view for displaying a list of items dynamically on Android.

Submarine Fully customizable floating navigation view for listing items dynamically on Android. Including in your project Gradle Add below codes to yo

Jaewoong Eum 460 Dec 21, 2022
BungeePluginManagerPlus - Dynamically manage your BungeeCord plugins

BungeePluginManagerPlus A plugin for BungeeCord / Waterfall that allows you to m

null 4 Jun 29, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Jan 8, 2023
A basic application demonstrating IPFS for collaborative data analysis, from the perspective of a Data Analysis Provider.

Spacebox A basic application demonstrating IPFS for collaborative data analysis, from the perspective of a Data Analysis Provider. Description This pr

null 0 Jan 15, 2022
Lightweight data loading and caching library for android

ColdStorage A lightweight data loading and caching library for android Quicklinks Feature requests: Got a new requirement? Request it here and it will

Cryptic Minds 41 Oct 17, 2022
Utility for developers and QAs what helps minimize time wasting on writing the same data for testing over and over again. Made by Stfalcon

Stfalcon Fixturer A Utility for developers and QAs which helps minimize time wasting on writing the same data for testing over and over again. You can

Stfalcon LLC 31 Nov 29, 2021
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
Kotlin Multiplatform project that gets network data from Food2Fork.ca

Food2Fork Recipe App This is the codebase for a Kotlin Multiplatform Mobile course. [Watch the course](https://codingwithmitch.com/courses/kotlin-mult

Mitch Tabian 317 Dec 30, 2022
Show weather data for the current location [Apollo Agriculture Interview Solution], for the Senior Android Engineer Role

Apollo Agriculture Android Take Home Assignment Writing Apollo Agriculture App using Android Architecture Components, in 100% Kotlin, using Android Je

Juma Allan 23 Nov 23, 2022