https://kotlinlang.org logo
#android
Title
# android
a

allan.conda

10/27/2020, 11:06 PM
Is wrapping LiveData into a delegate a good/bad idea?
Copy code
/**
 * Convenience property delegate for accessing and setting the live data value
 */
class LiveDataDelegate<T> : MutableLiveData<T> {

    constructor(value: T) : super(value)
    constructor() : super()

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = value
    operator fun setValue(thisObj: Any?, property: KProperty<*>, value: T?) {
        this.value = value
    }
}
So then I could do:
Copy code
// In Some ViewModel
private val stateDelegate = LiveDateDelegate(SomeState())
private var _state by stateDelegate
private val state: LiveData<SomeState> 
  get() = _state

fun onSomeUserEvent() {
  // no need to call state.value
  _state = _state.copy(
    // update the state
  )
}
Opinions are welcome
a

Adam Powell

10/27/2020, 11:17 PM
You can do this for any LiveData you might be using with the following:
Copy code
inline operator fun <T> LiveData<T>.getValue(thisObj: Any?, property: KProperty<*>): T = value

inline operator fun <T> MutableLiveData<T>.setValue(thisObj: Any?, property: KProperty<*>, value: T) {
    this.value = value
}
❤️ 1
a

allan.conda

10/27/2020, 11:20 PM
Ah! Right, liveData.observeAsState delegate was declared that way. Just curious if there’s drawbacks as it wasn’t part of the standard library. Was asking because I’m thinking of doing to same for MutableStateFlow (and replacing LiveData to remove eliminate nullability for state)
a

Ali Albaali

10/28/2020, 6:05 PM
If you do that then how can you observe/collect it?
a

Adam Powell

10/28/2020, 7:48 PM
you can't 🙂
if you write to it everywhere it can be kind of cute as your private interface to a hot data source, but ultimately it's kind of impractical outside of something like compose's snapshot state that tracks subscriptions implicitly
a

Ali Albaali

10/28/2020, 8:30 PM
Do you think it's possible to make the Views react to it when it's changed? Like how compose does it
a

Adam Powell

10/28/2020, 9:08 PM
databinding is one way, you could also use compose's snapshot system directly if you were so inclined. Probably a decent bit of manual wire-up to get there, but
snapshotFlow
might be interesting to you: https://developer.android.com/reference/kotlin/androidx/compose/runtime/snapshots/package-summary#snapshotflow
a

allan.conda

10/29/2020, 12:02 AM
If you do that then how can you observe/collect it? (edited)
Thinking along these lines
Copy code
// ViewModel
private val mutableStateFlow = mutableStateFlow(state)
private var _state by mutableStateFlow
val state: StateFlow<State>
  get() = _state

fun someFun() {
  _state = _state.copy(
    loading = true
  )
}

// Composable View
viewModel.state.collectAsState()
as alternative to a combine function where you write everything twice for every new property in the state
Copy code
combine(
  loading,
  items,
  // grows down
) { loading, items -> // grows
  State(
    loading = loading,
    items = items,
    // grows again
  ).collect {
    _state.value  = it
  }
}
2 Views