Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Read Only access of Immutable Type to an Internal Variable of a Mutable Type

While learning ViewModels in Android, a problem has arisen that feels like Kotlin was meant to solve. In the code below, we can see that MutableLiveData values are being use to edit values and indicators. However, we do not want these mutable values to be exposed to anything else, specifically members of an Android lifecycle. We DO want Android Lifecycle members to have access to read values but not set them. Therefore, the 3 exposed functions, displayed below, are of the LiveData<> immutable type.

Is there an easier or more concise way to expose read only values that can be edited internally? This seems like what Kotlin was made to avoid: boilerplate verbosity.

class HomeListViewModel: ViewModel(){
    //Private mutable data
    private val repositories = MutableLiveData<List<Repo>>()
    private val repoLoadError = MutableLiveData<Boolean>()
    private val loading = MutableLiveData<Boolean>()


    //Exposed uneditable LIveData
    fun getRepositories():LiveData<List<Repo>> = repositories
    fun getLoadError(): LiveData<Boolean> = repoLoadError
    fun getLoadingStatuses(): LiveData<Boolean> = loading

    init{...//Do some stuff to MutableLiveData<>

    }
}

A non-Android scenario that might be similar is:

class ImmutableAccessExample{

    private val theThingToBeEditedInternally = mutableListOf<String>()

    fun theThingToBeAccessedPublicly(): List<String> = theThingToBeEditedInternally

    init {
        theThingToBeEditedInternally.add(0, "something")
    }

}
like image 962
Josh Ribeiro Avatar asked Jan 23 '18 15:01

Josh Ribeiro


People also ask

What is the difference between Val and VAR in Kotlin?

var is like a general variable and can be assigned multiple times and is known as the mutable variable in Kotlin. Whereas val is a constant variable and can not be assigned multiple times and can be Initialized only single time and is known as the immutable variable in Kotlin.

How do you make a mutable variable in Kotlin?

Mutable variable: var keyword In kotlin, we use var keyword to declare a mutable variable. Lets take an example to understand this. In this example we have declared a mutable variable using var keyword, to demonstrate that we can change the value of it, we have reassigned a different value to myName variable.

What is the difference between Val and VAR?

The difference between val and var is that val makes a variable immutable — like final in Java — and var makes a variable mutable. Because val fields can't vary, some people refer to them as values rather than variables.

What does Val do in Kotlin?

Kotlin uses two different keywords to declare variables: val and var . Use val for a variable whose value never changes. You can't reassign a value to a variable that was declared using val .


2 Answers

I don't know if it is possible to avoid the verbosity. But, I've seen that before and it is usually declared as a property.

private val _repositories = MutableLiveData<List<Repo>>()
val repositories : LiveData<List<Repo>> 
    get() = _repositories

This is the convention, see the doc here in Names for backing properties

If a class has two properties which are conceptually the same but one is part of a public API and another is an implementation detail, use an underscore as the prefix for the name of the private property:

like image 200
crgarridos Avatar answered Sep 20 '22 05:09

crgarridos


Following the idea of this post:

class HomeListViewModel: ViewModel(){
    val repositories: LiveData<List<Repo>> = MutableLiveData()

    init {
        repositories as MutableLiveData
        ...//Do some stuff to repositories
    }
}
like image 33
aviyay Avatar answered Sep 21 '22 05:09

aviyay