Skip to content

Instantly share code, notes, and snippets.

rharter /
Created Sep 23, 2020
Using this script you can create a tiny macOS app that will always launch the latest version of any JetBrains Toolbox installed IDE. Simply pass the target IDE application as the first argument and the script will create a launcher that you can add to your dock that will always point to the latest installed version of the IDE.
APP_SCRIPT_NAME="$(ls "${APP_DIR}/Contents/MacOS/")"
APP_FILE_NAME="$(basename "${APP_DIR}")"
CHANNEL_DIR="$(dirname "$(dirname "$1")")"
TOOLBOX_APP_NAME="$(basename "$(dirname "$CHANNEL_DIR")")"
rharter / StoreRepository.kt
Created Aug 19, 2020
Extension function to convert a store, which emits a stream of **events**, to a repository which emits a stream of **states**. This hides implementation details, like which datasource is providing the data, from consumers.
View StoreRepository.kt
sealed class Resource<T> {
data class Loading<T>(val data: T? = null, val message: Int? = null) : Resource<T>()
data class Success<T>(val data: T) : Resource<T>()
data class Error<T>(val throwable: Throwable?, val data: T? = null) : Resource<T>()
fun <T> Resource<T>.dataOrNull(): T? = when (this) {
is Resource.Loading -> data
is Resource.Success -> data
is Resource.Error -> data
rharter / Scoped.kt
Last active Aug 9, 2022
A kotlin property delegate to scope any object to an android lifecycle. Blog post at
View Scoped.kt
import androidx.lifecycle.get
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
* Returns a property delegate to access the wrapped value, which will be retained for the
* duration of the lifecycle of this [ViewModelStoreOwner].

Dagger/Android with Internal Dependencies

I’ve figured out how to do what I wanted, though without some generation I’m not actually sure it’s worth it. Here’s a bunch more code with the solution I’ve figured out, in case anyone knows how to auto-generate this stuff, or if there’s a better way to do this.

The Goal: Allow use of Dagger-android AndroidInjectors without needing to make all dependencies of the target public.

The Scenario: I have a modular app where each feature is a separate module (among others). I have always hated making the ViewModels/ViewStates/ViewActions and other internal parts of the feature public, but that’s required with the current Dagger-android subcomponent approach.

Here’s my module setup:

rharter / InjectableActivityScenario.kt
Created Jul 19, 2019
An ActivityScenario that allows you to use Dagger Android's automatic, lifecycle based injection without making your Application class `open`, or overriding it in tests.
View InjectableActivityScenario.kt
package com.pixite.pigment.testing
import android.content.Context
import android.content.Intent
import androidx.lifecycle.Lifecycle
rharter / InjectableActivityTestRule.kt
Last active Dec 6, 2021
Test Rule that allows you to use Dagger Android's automatic lifecycle based injection without making your Application class `open`, or overriding it in tests.
View InjectableActivityTestRule.kt
package com.pixite.pigment.testing
import android.content.Context
import android.content.Intent
import android.os.Bundle
rharter / config.yaml
Created May 24, 2018
Example Circle CI config file
View config.yaml
version: 2.0
defaults: &defaults
- image: menny/android_ndk:latest
working_directory: ~/pigment
_JAVA_OPTIONS: "-Xmx1400m -XX:ParallelGCThreads=2 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -Djava.util.concurrent.ForkJoinPool.common.parallelism=2"
TERM: dumb
rharter / LiveEvent.kt
Last active Apr 8, 2020
LiveData that only delivers new events to observers.
View LiveEvent.kt
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.Observer
fun <T> LiveData<T>.toLiveEvent(): LiveEvent<T> {
return when (this) {
is LiveEvent -> this
else -> LiveEvent<T>().apply {
rharter / ViewCompatExt.kt
Last active Feb 4, 2018
Extension methods to easily provide all functionality in ViewCompat. This makes it super easy to see when there is a compat method available in code completion right alongside the framework methods.
View ViewCompatExt.kt
import android.content.ClipData
import android.os.Build
import android.os.Bundle
import android.view.*
rharter / SharedPreferenceLiveData.kt
Last active Jun 6, 2022
Creates LiveData objects that observe a value in SharedPreferences while they have active listeners.
View SharedPreferenceLiveData.kt
import android.arch.lifecycle.LiveData
import android.content.SharedPreferences
abstract class SharedPreferenceLiveData<T>(val sharedPrefs: SharedPreferences,
val key: String,
val defValue: T) : LiveData<T>() {
private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
if (key == this.key) {
value = getValueFromPreferences(key, defValue)