How to remove a single mapbox android annotation? - kotlin

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()

Related

Better code for mapping json objects with AWS Dynamo AttributeValues in Kotlin

I am using below code to map the json objects with AWS Dynamo DB attributes but I am not sure whether this will be having any performance issue or not? Please let me know if we have any other better way to achieve it.
I have list of maps and want store them in Dynamo. I am using AWS SDK V2 and Kotlin for it.
//items in model class
var items: List<Map<String, Any>>? = null
val itemValues = mutableMapOf<String, AttributeValue>()
itemValues.put("items", fromL(
order.items?.map { attributes ->
fromM(
attributes.mapValues { attribute ->
fromS(attribute.value.toString())
}
)
}
))
Above mentioned code is working but I want to know if there is any better way to do this.

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.

How can I make a mutable list of mutable maps?

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)

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)

Accessing Resources IDs using Kotlin & Anko

I am new to Android/Kotlin/Anko and I have a question regarding the way to access color (and probably other) resources from within Anko.
I know that there are helpers like textResource where you simply pass the R.string.my_color to simplify the process of setting resource strings but how about accessing colors using the Resources instance from the View class ?
Let’s say you have a subclass of Button and want to change the text color. If you use the textResource it will change the text string not the color, and if you use textColor then you must specify the real resource ID by using resources.getColor(R.color.my_color, null) which wouldn't be so annoying if you didn't have to pass the optional theme parameter (null here)
Is creating an extension on Resources useful here ?
fun Int.fromResources(resources: Resources): Int {
return resources.getColor(this, null)
}
What is the recommended way ?
EDIT
I changed the textColor value extension to do just that, which I found the cleanest thing to do except I have no idea if this is really Android friendly
var android.widget.TextView.textColor: Int
get() = throw AnkoException("'android.widget.TextView.textColor' property does not have a getter")
set(v) = setTextColor(resources.getColor(v, null))
I think you can use a property extension like this one instead of the one you suggested:
var TextView.textColorRes: Int
get() = throw PropertyWithoutGetterException("textColorRes")
set(#ColorRes v) = setTextColor(resources.getColor(v, null))
Or use ContextCompat as suggested by Damian Petla:
var TextView.textColorRes: Int
get() = throw PropertyWithoutGetterException("textColorRes")
set(#ColorRes v) = setTextColor(ContextCompat.getColor(context, v))
You should keep Anko's textColor:
Allows you to set a color directly without taking it from XML, if needed at some point
Prevents you from importing the wrong textColor (Anko's one or yours), same property names with different behaviour is not a good idea.