1

I'm using singleton object to hold data for the app which are changed or used on multiple places.

In my case, I have Arraylist of objects inside singleton. What I want to do is to iterate over this Arraylist and find one item with specific ID, then I want to copy this item and modify it. But what will happen is that If I copy this item from Singleton Arraylist and I will modify this coppied item, it will also modify that original item inside Singleton Arraylist.

Is there any way how to copy singleton item without acting like pointer?

Here is example code:

val foodList: ArrayList<Food> = AndroidSingleton.getInstance(this).foodList

val foodEntity: Food = foodList[1]
//foodList[1].foodID == 10 
foodEntity.foodID = 7

//After step above foodList[1].foodID == 7 --> But I want to change only foodEntity ID

//use of coppied food Entity elsewhere
return foodEntity

Singleton:

class AndroidSingleton private constructor(private val context: Context?){

    companion object : SingletonHolder<AndroidSingleton, Context>(::AndroidSingleton)

var foodList: ArrayList<Food> = ArrayList()


}

open class SingletonHolder<out T, in A>(creator: (A) -> T) {
    private var creator: ((A) -> T)? = creator
    @Volatile private var instance: T? = null

    fun getInstance(arg: A): T {
        val i = instance
        if (i != null) {
            return i
        }

        return synchronized(this) {
            val i2 = instance
            if (i2 != null) {
                i2
            } else {
                val created = creator!!(arg)
                instance = created
                creator = null
                created
            }
        }
    }
}
martin1337
  • 2,384
  • 6
  • 38
  • 85
  • Assigning an object to a variable _does not_ copy it. If you actually copy it, this will work (make a copy constructor). – Salem Sep 05 '18 at 11:12
  • It will copy it but it acts like pointer. If i change this coppied variable it will also change arraylist item at position 1 inside singleton. – martin1337 Sep 05 '18 at 11:13
  • 1
    NO, it does not copy anything. The reason why it "acts like a pointer" is because _it is the same object_. Java does not work like C++, everything (except primitives) are references. – Salem Sep 05 '18 at 11:13

1 Answers1

1

I would argue that mutating an object in this way should be avoided at all costs.

Luckily, Kotlin allows to achieve that using data classes with only value members:

data class Food(val foodID: Int, 
             /* probably more fields here */)

What's great about data classes is that they also support copy method out of the box:

return foodEntity.copy(foodID= 7)

That way you can avoid all your troubles altogether.

Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
  • This was the answer. I just coppied whole object. Reason for copy -> I have this arraylist of foods used in recyclerview. As I click on item it I can modify his attributes. As I modify his attributes, i click confirm button which will copy that item from that recyclerview, his modified version will be coppied to arraylist_2 but version of the item in arraylist_1 should be unchanged(you can create multiple versions of that one item and add them to arraylist_2). Without copying, each item from singleton arraylist would be changed to recent version of the arraylist_2 item. – martin1337 Sep 06 '18 at 09:48