How can I make a mutable list of mutable maps? - kotlin

My attempt:
val areas = mutableListOf<mutableMapOf<Double, Double>()>()
On mutableListOf it shows an error Function invocation 'mutableListOf(...)' expected

mutableMapOf<Double, Double>() is a function call that creates a map. You need to first create a list and only specify the type of its items, which is: MutableMap<Double, Double>:
val areas = mutableListOf<MutableMap<Double, Double>>()
Then you can add maps to it:
areas += mutableMapOf(1.0 to 1.0)

Related

How to remove a single mapbox android annotation?

I only started learning mapbox maps and I'm trying to remove a mapbox annotation every time I create another annotation.
My code:
bitmapFromDrawableRes(
this#PagePlanRouteMap,
R.drawable.red_marker
)?.let {
val annotationApi = mapView?.annotations
val pointAnnotationManager = annotationApi?.createPointAnnotationManager(mapView!!)
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(Point.fromLngLat(lng, lat))
.withIconImage(it)
pointAnnotationManager?.create(pointAnnotationOptions)
}
Can you help me implement the deleting of annotation using --
pointAnnotationManager?.deleteAll()
or is there another better way for this? Thanks.
You can use the delete() method from your pointAnnotationManager.
It has 2 different parameters you can pass through: either a PointAnnotation object or a list of PointAnnotation.
For example:
val pointAnnotation = pointAnnotationManager?.create(pointAnnotationOptions)
pointAnnotationManager?.delete(pointAnnotation)
OR
pointAnnotationManager?.delete(listOf(pointAnnotation))
pointAnnotationManager?.deleteAll() is not working for me if you want to delete all points you can use this
binding.mapView.annotations.cleanup()

Jetpack compose not recomposing view on value change

I am using objectbox and attempting to force recomp on my lazy column with information from the viewModel.
I currently use a method that has been state hoisted to the view model but can't seem to retrieve the value in the view model and force recomp.
In my view model (DataFieldsViewModel), I've obtained all the Data Fields like this:
private val _dataFieldsBox = ObjectBox.get().boxFor(DataField::class.java)
var dataFieldsBox: Box<DataField> = _dataFieldsBox
and then it is passed in the composable screen using
fields = viewModel.dataFieldsBox
and the data fields object removed with
is DataFieldEvent.ConfirmDelete -> {
_deletedDataField.value = event.dataField
_dataFieldsBox.remove(deletedDataField.value)
}
the reference for deletedDataField is kept so that it can be restored from a snack bar.
The delete works, the restore works, it's just that the lazy column does not update until I click another view that forces recomp. I've even mocked up a simple button with state hoisted increment and decrement methods and a value in the view model to test out recomp and got that working pretty quick, just don't know how to do it for these ObjectBox DataField objects
Edit 18/08
Tried using mutableStateOf
private var _dataFieldsBox = ObjectBox.get().boxFor(DataField::class.java)
var dataFieldsBox = mutableStateOf(_dataFieldsBox)
and then attempting to collect the value with
val fields by viewModel.dataFieldsBox
and then deleting with
_deletedDataField.value = event.dataField
_dataFieldsBox.remove(event.dataField)
only fix right now is the two hacky ways which i don't like. I read something about despite the values in a mutable list changing because the reference is the same the recomp doesn't happen to save on recomps.
So tried to amend the list and then duplicate with new values which also did nothing.
is DataFieldEvent.ConfirmDelete -> {
_deletedDataField.value = event.dataField
_dataFieldsBox.remove(event.dataField)
val newList = _dataFieldsBox
dataFieldsBox = mutableStateOf(newList)
}
Would be helpful if you update viewmodel code you are having.
Not worked on ObjectBox. With your current code, here is the thing.
Composable function will recompose when it is able to listen to changes. For normal variable it does not listen to changes. You can make them listen in several ways.
You can do it with mutableStateOf(). You can have mutableState variable which takes type of _dataFieldsBox . And so can access it by viewModel._dataFieldsBox.value.
private val _dataFieldsBox = ObjectBox.get().boxFor(DataField::class.java
var _dataFieldsBox = mutableStateOf(_dataFieldsBox)
And then in view model,
_dataFieldsBox.value.remove(_dataFieldsBox) // This will remove the value in the state variable and composable function will recompose.
You can also use LiveData and observe for the changes and it will recompose.

adding to a list that is contained in livedata and adding elements to that list

adding to a list that is contained in livedata and adding elements to that list
val resourcesLiveData by lazy { MutableLiveData<List<File>>() }
I thought this should work as my LiveData is a list of files and I just want to add elements to it. But the value of live data is always an empty list. The res is the different file resources I am trying to add
resourceLiveData.value?.toMutableList()?.add(res)
So I tried it more expicity using this version but the list is still empty
val listOfRes = resourceLiveData.value ?: emptyList()
listOfRes.toMutableList().add(res)
resourceLiveData.value = listOfRes.toList()
Can anyone see if I am doing something wrong.
Just want to add to the list that is contained in the value
Agree to #KeyserSoze answer, if you have to use only List then you can do below
resourceLiveData.value = resourceLiveData.value?.toMutableList()?.apply { add(res) }?: emptyList()
You are creating a new object by calling toMutableList() instead of updating the original.
Change your LiveData type to MutableList:
val resourcesLiveData by lazy { MutableLiveData<MutableList<File>>() }
Then, update the value accordingly:
resourceLiveData.value?.add(res)

How to copy or clone mutableList of data object without using collection map in Kotlin

I create copy of one MutableList. When I update element value of copy MutableList But Original List element value also changed. When I use map It working fine but It is like a iteration of whole list, Is any way to do achieve without iteration ? how to copy elements of the MutableList.
val array: MutableList<UserData> = ArrayList()
val userData = UserData("DataOne")
array.add(userData)
val arrayCopy = ImmutableList.copyOf(array)// not working
//val arrayCopy = array.toMutableList()// not working
// val arrayCopy = array.map { it.copy() }.toMutableList()//working
Log.i("----> array ", array[0].name)//print DataOne
Log.i("----> arrayCopy ", arrayCopy[0].name)//print DataOne
arrayCopy[0].name = "DataTwo"
Log.d("----> array ", array[0].name)//print DataTwo
Log.d("----> arrayCopy", arrayCopy[0].name) //print DataTwo
ImmutableList.copyOf does copy the list. The problem is that you want to copy elements of the list as well. Of course you have to iterate over the list to do that, but so does copyOf and I don't see why you expect it's possible to avoid. A slightly better version of map is
array.mapTo(mutableListOf()) { it.copy() }
because it iterates only once.
Sorry but there wouldn't be any other way cause to convert one element you will have to read/copy it once, for n number of element you'll have to iterate n times to get the proper copy.
The only other way I can think of is to create the desired immutable/mutable list in the first place and not copying it all at once later.
Hope this helps

how to add Array index value in Kotlin?

first, I create empty Array(Kotlin) instance in companion object.
companion object {
var strarray: Array<String> = arrayOf()
var objectarray: LinkedHashMap<Int, List<Any>> = LinkedHashMap<Int, List<Any>>()
}
and I expected that I use empty array instance when read textString from CSV File.
fun csvFileToString():String {
val inputStream = File(Paths.get("").toAbsolutePath().toString()
.plus("/src/main/SampleCSVFile_2kb.csv")).inputStream()
val reader = inputStream.bufferedReader()
var iterator = reader.lineSequence().iterator()
var index:Int = 1;
while (iterator.hasNext()){
var lineText:String = iterator.next()
strarray.set(index, lineText)
index++
}
return ""
}
but when I run that source code
a.csvFileToString()
println(CsvParser.strarray)
occured exception
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
strarray.set(index, lineText) <<<<<<<<< because of this line
can I use Array(from kotlin collection) like ArrayList(from java collection)?
You can add a new item to an array using +=, for example: item += item
private var songs: Array<String> = arrayOf()
fun add(input: String) {
songs += input
}
Size of Array is defined at its creation and cannot be modified - in your example it equals 0.
If you want to create Array with dynamic size you should use ArrayList.
arrayOf gives you an array. Arrays have fixed length even in Java.
listOf gives you an immutable list. You cannot add or remove items in this list.
What you're looking for is mutableListOf<String>.
In your current approach, reusing a member property, don't forget to clear the list before every use.
Your code can be further simplified (and improved) like so:
out.clear()
inputStream.bufferedReader().use { reader -> // Use takes care of closing reader.
val lines = reader.lineSequence()
out.addAll(lines) // MutableList can add all from sequence.
}
Now imagine you wanted to consume the output list but needed to parse another file at the same time.
Consider working towards a pure function (no side effects, for now no accessing member properties) and simplifying it even further:
fun csvFileToString(): String { // Now method returns something useful.
val inputStream = File(Paths.get("").toAbsolutePath().toString()
.plus("/src/main/SampleCSVFile_2kb.csv")).inputStream()
inputStream.bufferedReader().use {
return it.lineSequence().joinToString("\n")
}
}
In this case we can totally skip the lists and arrays and just read the text:
inputStream.bufferedReader().use {
return it.readText()
}
I'm assuming that's what you wanted in the first place.
Kotlin has a lot of useful extension functions built-in. Look for them first.