Skip to content

Instantly share code, notes, and snippets.

@jmatsu
Last active December 1, 2018 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmatsu/536bdc7d453213b3817085c850a45484 to your computer and use it in GitHub Desktop.
Save jmatsu/536bdc7d453213b3817085c850a45484 to your computer and use it in GitHub Desktop.
import android.app.Application
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
class MainActivity : AppCompatActivity() {
class MainViewModel(application: Application) : ViewModel(application) {
val textLiveData: LiveData<String> by liveData(MutableLiveData())
val mutableLiveData: LiveData<String> = MutableLiveData()
val crashTextLiveData: LiveData<String> by liveData(NotMutableLiveData())
private class NotMutableLiveData : LiveData<String>() {
fun updateText(text: String) {
value = text
}
}
fun updateTextLiveData(text: String) {
textLiveData.mutate().value = text
}
fun updateMutableLiveData(text: String) {
mutableLiveData.mutate().value = text
}
fun updateCrashTextLiveDataSafely(text: String) {
(crashTextLiveData as NotMutableLiveData).updateText(text)
}
fun crash(text: String) {
crashTextLiveData.mutate().value = text
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.hello)
val textView1 = findViewById<TextView>(R.id.hello1)
val textView2 = findViewById<TextView>(R.id.hello2)
val vm = ViewModelProviders.of(this).get(MainViewModel::class.java)
vm.textLiveData.observe(this, Observer {
textView.text = "textLiveData:$it"
})
vm.mutableLiveData.observe(this, Observer {
textView1.text = "textLiveData:$it"
})
vm.crashTextLiveData.observe(this, Observer {
textView2.text = "crashTextLiveData:$it"
})
findViewById<View>(R.id.helloButton).setOnClickListener {
vm.updateTextLiveData("hello!")
}
findViewById<View>(R.id.hello1Button).setOnClickListener {
vm.updateMutableLiveData("hello1")
}
findViewById<View>(R.id.hello2Button).setOnClickListener {
vm.updateCrashTextLiveDataSafely("hello2")
}
findViewById<View>(R.id.crash).setOnClickListener {
vm.crash("crash...")
}
}
}
import android.app.Application
import androidx.annotation.CallSuper
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
open class ViewModel(application: Application) : AndroidViewModel(application) {
protected fun <T> LiveData<T>.mutate(): MutableLiveData<T> {
return when (this) {
is LiveDataWrapper -> this.wrappedLiveData
is MutableLiveData -> this
else -> throw IllegalArgumentException("the given live data is not wrapped. Please use liveData delegation at declarations.")
}
}
protected inline fun <reified T> lazyLiveData(crossinline initializer: () -> LiveData<T>): Lazy<LiveData<T>> {
return lazy {
val liveData = initializer()
if (liveData is MutableLiveData) {
LiveDataWrapper(liveData)
} else {
liveData
}
}
}
protected inline fun <reified T> liveData(liveData: LiveData<T>): Lazy<LiveData<T>> {
return lazyOf(
if (liveData is MutableLiveData) {
LiveDataWrapper(liveData)
} else {
liveData
}
)
}
protected class LiveDataWrapper<T>(val wrappedLiveData: MutableLiveData<T>) : LiveData<T>() {
private val observer: Observer<T> = Observer { super.setValue(it) }
@CallSuper
override fun onActive() {
wrappedLiveData.observeForever(observer)
}
@CallSuper
override fun onInactive() {
wrappedLiveData.removeObserver(observer)
}
override fun postValue(value: T) {
wrappedLiveData.postValue(value)
}
override fun setValue(value: T) {
wrappedLiveData.value = value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment