Private setter vs Backing Property in Kotlin - android

I'm an old Java fan and trying to understand Kotlin basics. Can someone tell me what is the difference between these codes:
private val _users = mutableListOf<User>()
val users: List<User>
get() = _users
VS
var _users: mutableListOf<User>()
private set
As far as understand, upper code provides set _users only in that class and get it publicly which seems pretty same with the code below but in Google docs they say it's backing property which i don't get what it is.

Both examples are really totally different. You need to understand the difference between:
val MutableList
and:
var List
First makes possible to modify the contents of a list, but you can't replace the list object itself. Second, you can replace the list object, but you cannot modify its contents. This isn't really specific to Kotlin, it is the same in Java. val (or making a setter private) is like final field and List is like wrapping a list with Collections.unmodifiableList() - they're different things.
In your first example, neither the external nor internal code can replace the list, but internal code can modify its contents - external can't. In second example both internal and external code can modify contents of the list, but only internal code can replace the list entirely.

Related

Efficient way to create like 1000 instance of a class

As a newbie in Kotlin, i want to ask a question. Let’s say that i have class Dog like below,
data class Dog(val breed : String, val gender : String, val name : String, val age: Int){}
I want to make 1000 instances of this Dog class and add all of instances in an arrayList and later i will use this list in different activities. Imagine that I have an activity which only shows Labradors . So i have to take that arrayList which contains all of my Dogs and filter the breed according to Labrador and show the user.
As i read in articles i think this is an expensive way but i don’t know what the efficient way is to do this. Cause i will create all instances manually like below.
fun dogMaker(){
val dog1 = Dog("example","example","example",1)
val dog2 = Dog("example","example","example",1)
val dog3 = Dog("example","example","example",1)
val dog4 = Dog("example","example","example",1)
val dog5 = Dog("example","example","example",1)
//... goes on...
}
Could you suggest me an efficient way? Thanks in advance.
As a beginner, don't even worry about trying to optimize this. Just use a FOR loop or initialize the array manually and it'll be fine. If you want to access it in different Activities, just make the ArrayList a global variable by declaring it outside of one of your classes. In your case, this means declaring it above MainActivity.
The better but more involved way to do it is to store all these items in a pre-populated database. That way, you're not creating an ArrayList every time the app runs, you're not taking up memory unnecessarily, and you're only accessing what you need at any given time.

Kotlin backing property in Android ViewModel

Was just wondering, why is it better to use backing property for MutableLiveData, instead of just exposing getter function that returns the MutableLiveData property as live data. For example:
Why this code
private val _registeredDevicesObservable: MediatorLiveData<List<Data>> = MediatorLiveData()
val registeredDevicesObservable: LiveData<List<Data>> = _registeredDevicesObservable
is better or more acceptable than this one
private val _registeredDevicesObservable: MediatorLiveData<List<Data>> = MediatorLiveData()
fun registeredDevicesObservable(): LiveData<List<Data>> = _registeredDevicesObservable
As also when this getter function is keeping the LiveData immutability and keeps me from having that little annoying underscore syntax when accessing the property inside the view model.
It's just less idiomatic in the language to use a function that simply returns an already-available object. You're free to do it any way you like, but if others have to work with your code, it will be easier to understand and work with if you follow general conventions.
There isn't as strong a convention about whether the backing property should have a leading underscore in the name, so if you don't like it, don't use it.
One reason to stick with these conventions is there is a proposed upcoming language feature to allow you to do this without a backing property, and so if you're following the conventions, it will be very easy to update your code to eliminate the backing property.

Is it proper to use ViewModel for the ListView and the <T> in the ListView?

Preamble
In trying to get my head around the Kotlin classes to implement Android's ViewModel (and MVVM pattern) as used with Fragments and Activities, it is not clear to me of the trade-offs among the various complex classes especially how they have inherited implicit operations and visible methods (e.g., from the observer objects, managed scope, etc.) versus the old O-O approach of passing list-items and lists between activities in an intent as a bundle or reference, etc.
To illustrate my learning dilemma, I am implementing a crunchy cookie and and a jar to contain the cookies. The cookies can be created, consumed and viewed inside the cookie jar.
Android code tends to be vague on details of classes and the tutorials use deprecated versions, so it is difficult to follow best-practices with the latest version of the Android Architecture Component libraries.
Pseudo Kotlin code:
data class CrunchieCookie : {
var flavor: String?
var calories: String?
var photo: ImageView?
}
class CrunchieCookieViewModel : ViewModel() {
val _crunchieCookie: CrunchieCookie?
val crunchieCookie: CrunchieCookie = _crunchieCookie
}
class CookieJarListViewModel: ViewModel() {
val _cookieJar: MutableLiveData<CrunchieCookie>?
val cookieJar: LiveData<CrunchieCookie> = _cookieJar
}
Purpose
I am expecting to create, update and destroy crunchie-cookies
I am expecting to put crunchie-cookies in a cookie-jar (and take them out)
I am expecting to list all the crunchie-cookies in the cookie-jar in a scrolling ListView
I am expecting to click on a crunchie-cooking in the cookie-jar to open an detail view of the cookie
Finally, storing the cookie-jar in a remote DB, so planning for the local/remote data-source in the future
So, to my way of thinking, the cookie viewmodel will be used in CRUD operations and reused in the detail view from the list model.
MAKING #Tenfour04 's COMMENT AN ANSWER.
Your ViewModel should have a LiveData<List>. The Fragment containing the ListView should observe the LiveData for changes and pass the List along to the ListView when the LiveData value changes. If you're actually just modifying the contents of a MutableList, then you need to set the value of the MutableLiveData to that same list to inform it that there's a change it needs to notify observers about. – Tenfour04 Sep 9 at 0:02

Using Kotlin's MutableList or ArrayList where lists are needed in Android

I am trying to learn the "Kotlin native way" to do things in Android, while being an expert in neither Kotlin, Java, nor Android development. Specifically, when to use ArrayList versus MutableList.
It seems to me that MutableList should be chosen whenever possible. Yet, if I look at Android examples, they seem to always choose the ArrayList (as far as I've found so far).
Below is a snippet of a working example that uses ArrayList and extends Java's RecyclerView.Adapter.
class PersonListAdapter(private val list: ArrayList<Person>,
private val context: Context) : RecyclerView.Adapter<PersonListAdapter.ViewHolder>() {
Question 1)
Could I simply write the above code as follows (note MutableList<> instead of ArrayList<>), even though I am borrowing from Android's Java code?
class PersonListAdapter(private val list: MutableList<Person>,
private val context: Context) : RecyclerView.Adapter<PersonListAdapter.ViewHolder>() {
Question 2)
Is it really better to always use MutableList over ArrayList? What are the main reasons? Some of that link I provide above goes over my head, but it seems to me that MutableList is a looser implementation that is more capable of changing and improving in the future. Is that right?
The difference is:
if you use ArrayList() you are explicitly saying "I want this to be an ArrayList implementation of MutableList and never change to anything else".
If you use mutableListOf() it is like saying "Give me the default MutableList implementation".
Current default implementation of the MutableList (mutableListOf()) returns an ArrayList. If in the (unlikely) event of this ever changing in the future (if a new more efficient implementation gets designed) this could change to ...mutableListOf(): MutableList<T> = SomeNewMoreEfficientList().
In that case, wherever in your code you used ArrayList() this will stay ArrayList. Wherever you have used mutableListOf() this would change from ArrayList to the brilliantly named SomeNewMoreEfficientList.
ArrayList is an implementation of the MutableList interface in Kotlin:
class ArrayList<E> : MutableList<E>, RandomAccess
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-array-list/index.html
That answer may indicate that MutableList should be chosen whenever possible, but ArrayList is a MutableList. So if you're already using ArrayList, there's really no reason to use MutableList instead, especially since you can't actually directly create an instance of it (MutableList is an interface, not a class).
In fact, if you look at the mutableListOf() Kotlin extension method:
public inline fun <T> mutableListOf(): MutableList<T> = ArrayList()
you can see that it just returns an ArrayList of the elements you supplied.

ViewModel backing properties [kotlin]

Looking to the code of some Google's demo app (like sunflower or Google io 2018 app) and I've noticed that for the viemodels' backing properties they use a separate instance of the same type with a custom getter; like this:
private val _userData: MutableLiveData<User>
val userData: LiveData<User>
get() = _userData
but why do they do that? Isn't better to directly make the _userData accessible?
Could it be because while _userData is a MutableLiveData they don't want the observer to be able to change the value?
userData which is exposed to the Activity or Fragment must be immutable since the view only needs to observe to the LiveData. So, we need to make the actual _userData returns a LiveData.
One way is using the Kotlin coding convention and create two variables, _userData and userData, one is mutable and another one is not:
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.

Categories

Resources