0

I'm having an issue where I assign a variable based on data that is being received from a server (in JSON). I have two class variables

  1. teams - which will be changed based on user interaction
  2. reset_teams - which should always stay the same as the original list so that a user can reset all values whenever they choose.

These variables are used to (re-)populate a RecyclerView at various times based on user interaction (i.e., pressing a button inside of the app)

My problem is that any time I make a change to an object in the teams ArrayList, it also makes a change to the reset_teams ArrayList, as if they are somehow connected (similar to pass by value/reference in a function).

I am somewhat new to Kotlin, so it's quite possible I am missing something, but I'm wondering how I can keep the reset_teams ArrayList exactly the same at all times, even if the teams ArrayList has changes to different properties of the objects it stores?

// Class variables
var teams: ArrayList<myObject> = ArrayList()
var reset_teams: ArrayList<myObject> = ArrayList()

// Function to handle JSON after receiving data from remote server
private fun handleJson(jsonString: String?) {
    val jsonArray = JSONArray(jsonString)

    val list = ArrayList<myObject>()

    var x = 0

    while (x < jsonArray.length()) {
        val jsonObject = jsonArray.getJSONObject(x)


        list.add(
            myObject(// a bunch of code to make an object of type myObject)
        )
        x++
    }

    teams = list
    reset_teams = list

    test()  // Change a property
}


private fun test(){
    teams[0].someProperty = 10
    println(teams)      // The someProperty of the first element of the ArrayList has been correctly assigned to 10
    println(reset_teams) // The someProperty of the first element of the ArrayList has been changed to 10 even though the reset_teams was never assigned a new value
}
0

1 Answer 1

1

By assigning

teams = list
reset_teams = list

both list teams and list reset_teams reference the same list (space) in memory (heap). With teams[0].someProperty = 10 you change someProperty of the first element of this referenced list to 10. Since reset_teams references the same list, it also shows the changes.

In order to fix this unintended behaviour you will have to add copies of the objects to both lists teams and reset_teams. If class myObject is a data class, then you can add a copy by calling teams.add(m.copy()) where m is an instance of class myObject.

Remarks:

  • use camelCase for variable names: resetTeams instead of reset_teams
  • start class names with a capital letter: MyObject instead of myObject
  • prefer immutable objects if possible
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your comment Michael. That makes sense to me and I understand why the reference to the same memory is causing the issue. Can you explain to me how to 'add copies of the objects to both lists'? I tried setting teams = ArrayList(list) and reset_teams = ArrayList(list) both this does not fix the problem. Thanks
Hmmm, that ought to fix the problem… Can you double-check? A similar alternative: teams.clear(); teams.addAll(list); reset_teams.clear(); reset_teams.addAll(list). (You could then make their references vals. Or if you create new lists, you could make their references List<myObject>, i.e. nullable and immutable. In general, I find it's often a code smell to have a mutable list with a mutable reference.)
By the way, it's conventional to use camelCase, not snake_case, for identifiers in Kotlin: resetTeams instead of reset_teams. And PascalCase for classes and object types: MyObject instead of myObject. (That won't affect how it runs, of course, but would make it slightly easier for idiots like me to follow!)
Thanks for the Kotlin conventions. I will adhere to that moving forward. For consistency's sake in this thread I will continue using the original that I posted. It is strange, even if I: teams.clear(); teams.addAll(list); reset_teams.clear(); reset_teams.addAll(list); teams[0].someProperty = 99 println(reset_teams) println(teams) both lists are exactly the same. They are also declared as 'val'
I created a bit of a workaround that does work, but it unfortunately doesn't really solve the problem. Oh well, c'est la vie
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.