add null in the list of model data arrays kotlin android

Issue

Why can’t I add null in the list of model data arrays in Kotlin language?

enter image description here

adapterPaging!!.setOnLoadMoreListener {
            var customersModels: List<CustomersModel> = ArrayList()
            customersModels.add(null)
        }

Solution

var customersModels: List<CustomersModel> = ArrayList()

Your problem(?) here is polymorphism. You’ve defined customersModels as a List, which in Kotlin is explicitly immutable. You can’t add things to it.

Methods in this interface support only read-only access to the list; read/write access is supported through the MutableList interface.

You’re assigning an ArrayList to that variable, which is an object that does have the add method. And an ArrayList is a List, so you can do that. Like how a pencil is a writing tool that’s erasable, if someone just needs something to write with, you can give them a pencil or a pen. All they’ve asked for is something that writes.

But the variable you’re interacting with, customersModels, is explicitly a reference to a Kotlin List – a more restrictive subtype of MutableList*. It knows nothing about what that object actually is, just that it fits the immutable List type. That type does not have an add method so you can’t call it. Same as how if you ask for a writing tool, you can’t assume you’ll be able to erase what you write.


So you have three options here (let’s not get into reflection):

You can cast that variable to another type:

// or 'as ArrayList' if you really need to be that specific for some reason - you probably don't
(customersModels as MutableList).add(thing)

This is an unchecked cast – you’re telling the compiler "hey I know what this is, you don’t but you’re just gonna have to trust me on this one". This is unsafe, because there’s no protection, the compiler can’t do any checking and force you to handle potential problems. (Don’t do this)

A better approach is to actually check as you cast – there are two ways to do this in Kotlin:

// confirm the object's type - this will result in a 'smart cast' because the compiler
// can see that you're handling it safely, so it basically allows you to treat
// myList as that type
if (myList is MutableList) myList.add(thing)

// same deal but you can cast with a null fallback if it fails, then null-check the result
(myList as? MutableList)?.add(thing)

This is good for things where you handle a more general type, but you might want to get specific and handle different member types in different ways. Especially common if you’re using sealed classes.


The last approach is to just use the appropriate type in the first place!

// MutableList, since you want to mutate it by adding stuff
var customersModels: MutableList<CustomersModel> = ArrayList()
customersModels.add(null)

You’re creating a list you want to change – so that’s a MutableList, and that’s what customersModels should be. This kind of thing can be internal – you can expose that list as a List rather than a MutableList, so that other stuff that uses it sees it as a fixed, immutable list. If you’ve used LiveData you’ve probably seen this approach:

private val _myData = MutableLiveData<String>("hi")
val myData: LiveData<String> = _myData

myData is literally pointing at that MutableLiveData object, but because its type is just LiveData (the immutable kind) that means stuff that accesses that public variable see an object they can’t change. Really they could cast it to MutableLiveData and mess with it, but it’s less a security feature and more of an organisational thing. Make it clear how stuff is meant to be used, how you interact with it, etc. If you want to update, go through a specific function, that kind of thing.

So use List if it’s just a list that’s meant to be read, not written to. If it will/might be changed, use the MutableList type. This makes it clearer about what’s going on.

Also, generally you shouldn’t use explicit types like ArrayList – Kotlin has a bunch of functions to generate Lists and MutableLists, which makes it easier to reason about what you’re doing and why:

val numbers = List(5) { it + 1 }
val greetings = mutableListOf("hi", "hey", "sup")

Notice I’m not specifying the type next to the variable, it’s getting inferred by the function I’m using. So there’s no "treat this mutable list as an immutable one" going on (unless you need to do that for a specific reason!)

Answered By – cactustictacs

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published