How do I notify observers when my value is updated?

I am trying to modify some data from API. I have successfully implemented callbacks inside a nested recyclerview. But my selector doesn’t work now. Why is that and how do I fix it?

Below are the adapter classes.

Survey Container Adapter

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class SurveyContainerAdapter(
private val surveyList: ArrayList<DataSurvey>,
private val context: Context,
) :
RecyclerView.Adapter<SurveyContainerAdapter.SurveyContainerViewHolder>() {
private var onItemClickCallback: OnItemClickCallback? = null
inner class SurveyContainerViewHolder(val binding: SurveyContainerLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(surveyData: DataSurvey, position: Int) {
binding.tvSurveyTitle.text = "${surveyData.name} (${position + 1}/$itemCount)"
binding.ivCloseSurvey.setOnClickListener {
onItemClickCallback?.onItemClicked(surveyData, position)
}
if (surveyData.assets.isNotEmpty()) {
binding.ivCloseSurvey.visibility = View.GONE
}
binding.rvSurveyItem.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
val adapterItem = SurveyItemAdapter(surveyData.items)
adapterItem.setOnValueCallback(object : SurveyItemAdapter.SurveyItemListener{
override fun onValueChanged(surveyId: String, itemId: String, newValue: Any?) {
onItemClickCallback?.onValueClicked(surveyId, itemId, newValue)
}
})
binding.rvSurveyItem.adapter = adapterItem
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyContainerViewHolder {
val view =
SurveyContainerLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SurveyContainerViewHolder(view)
}
override fun getItemCount(): Int = surveyList.size
interface OnItemClickCallback {
fun onItemClicked(data: DataSurvey, position: Int)
fun onValueClicked(surveyId: String, itemId: String, newValue: Any?)
}
fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback) {
this.onItemClickCallback = onItemClickCallback
}
override fun onBindViewHolder(holder: SurveyContainerViewHolder, position: Int) {
holder.bind(surveyList[position], position)
}
}
</code>
<code>class SurveyContainerAdapter( private val surveyList: ArrayList<DataSurvey>, private val context: Context, ) : RecyclerView.Adapter<SurveyContainerAdapter.SurveyContainerViewHolder>() { private var onItemClickCallback: OnItemClickCallback? = null inner class SurveyContainerViewHolder(val binding: SurveyContainerLayoutBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(surveyData: DataSurvey, position: Int) { binding.tvSurveyTitle.text = "${surveyData.name} (${position + 1}/$itemCount)" binding.ivCloseSurvey.setOnClickListener { onItemClickCallback?.onItemClicked(surveyData, position) } if (surveyData.assets.isNotEmpty()) { binding.ivCloseSurvey.visibility = View.GONE } binding.rvSurveyItem.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) val adapterItem = SurveyItemAdapter(surveyData.items) adapterItem.setOnValueCallback(object : SurveyItemAdapter.SurveyItemListener{ override fun onValueChanged(surveyId: String, itemId: String, newValue: Any?) { onItemClickCallback?.onValueClicked(surveyId, itemId, newValue) } }) binding.rvSurveyItem.adapter = adapterItem } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyContainerViewHolder { val view = SurveyContainerLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false) return SurveyContainerViewHolder(view) } override fun getItemCount(): Int = surveyList.size interface OnItemClickCallback { fun onItemClicked(data: DataSurvey, position: Int) fun onValueClicked(surveyId: String, itemId: String, newValue: Any?) } fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback) { this.onItemClickCallback = onItemClickCallback } override fun onBindViewHolder(holder: SurveyContainerViewHolder, position: Int) { holder.bind(surveyList[position], position) } } </code>
class SurveyContainerAdapter(
    private val surveyList: ArrayList<DataSurvey>,
    private val context: Context,
) :
    RecyclerView.Adapter<SurveyContainerAdapter.SurveyContainerViewHolder>() {

    private var onItemClickCallback: OnItemClickCallback? = null

    inner class SurveyContainerViewHolder(val binding: SurveyContainerLayoutBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(surveyData: DataSurvey, position: Int) {
            binding.tvSurveyTitle.text = "${surveyData.name} (${position + 1}/$itemCount)"
            binding.ivCloseSurvey.setOnClickListener {
                onItemClickCallback?.onItemClicked(surveyData, position)
            }

            if (surveyData.assets.isNotEmpty()) {
                binding.ivCloseSurvey.visibility = View.GONE
            }

            binding.rvSurveyItem.layoutManager =
                LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
            val adapterItem = SurveyItemAdapter(surveyData.items)
            adapterItem.setOnValueCallback(object : SurveyItemAdapter.SurveyItemListener{
                override fun onValueChanged(surveyId: String, itemId: String, newValue: Any?) {
                    onItemClickCallback?.onValueClicked(surveyId, itemId, newValue)
                }
            })
            binding.rvSurveyItem.adapter = adapterItem
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyContainerViewHolder {
        val view =
            SurveyContainerLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return SurveyContainerViewHolder(view)
    }

    override fun getItemCount(): Int = surveyList.size

    interface OnItemClickCallback {
        fun onItemClicked(data: DataSurvey, position: Int)
        fun onValueClicked(surveyId: String, itemId: String, newValue: Any?)
    }

    fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback) {
        this.onItemClickCallback = onItemClickCallback
    }


    override fun onBindViewHolder(holder: SurveyContainerViewHolder, position: Int) {
        holder.bind(surveyList[position], position)
    }
}

Survey Item Adapter

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>package com.envisions.people.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.envisions.people.R
import com.envisions.people.api.responses.SurveyItem
import com.envisions.people.databinding.SurveyItemLayoutBinding
class SurveyItemAdapter(
private val surveyItemList: List<SurveyItem>
) :
RecyclerView.Adapter<SurveyItemAdapter.SurveyItemViewHolder>() {
private var surveyItemListener : SurveyItemListener? = null
inner class SurveyItemViewHolder(private val binding: SurveyItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(surveyData: SurveyItem, position: Int) {
binding.tvSurveyItemTitle.text = "${position + 1}. ${surveyData.name}"
if (position == itemCount - 1) {
binding.surveyItemSeparator.visibility = View.GONE
}
binding.cbConfirmSurveyItem.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
buttonView.isChecked = true
binding.cbCancelSurveyItem.isChecked = false
// binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel)
} else {
buttonView.isChecked = false
binding.cbCancelSurveyItem.isChecked = true
// binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel_red)
}
surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, isChecked)
// Log.e("value on cbConfirm", "value : ${surveyData.valueItem}")
// Log.e("value survey Item id", "value : ${surveyData.surveyId}")
// Log.e("value survey id", "value : ${surveyData.id}")
}
binding.cbCancelSurveyItem.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
buttonView.isChecked = true
binding.cbConfirmSurveyItem.isChecked = false
} else {
buttonView.isChecked = false
binding.cbConfirmSurveyItem.isChecked = true
}
surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, !isChecked)
//
// Log.e("value on cbCancel", "value : ${surveyData.valueItem}")
// Log.e("value survey Item id", "value : ${surveyData.surveyId}")
// Log.e("value survey id", "value : ${surveyData.id}")
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyItemViewHolder {
val view =
SurveyItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SurveyItemViewHolder(view)
}
override fun getItemCount(): Int = surveyItemList.size
override fun onBindViewHolder(holder: SurveyItemViewHolder, position: Int) {
holder.bind(surveyItemList[position], position)
}
fun setOnValueCallback(onValueClickCallback: SurveyItemListener) {
this.surveyItemListener = onValueClickCallback
}
interface SurveyItemListener {
fun onValueChanged(surveyId: String, itemId: String, newValue: Any?)
}
}
</code>
<code>package com.envisions.people.adapter import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.envisions.people.R import com.envisions.people.api.responses.SurveyItem import com.envisions.people.databinding.SurveyItemLayoutBinding class SurveyItemAdapter( private val surveyItemList: List<SurveyItem> ) : RecyclerView.Adapter<SurveyItemAdapter.SurveyItemViewHolder>() { private var surveyItemListener : SurveyItemListener? = null inner class SurveyItemViewHolder(private val binding: SurveyItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(surveyData: SurveyItem, position: Int) { binding.tvSurveyItemTitle.text = "${position + 1}. ${surveyData.name}" if (position == itemCount - 1) { binding.surveyItemSeparator.visibility = View.GONE } binding.cbConfirmSurveyItem.setOnCheckedChangeListener { buttonView, isChecked -> if (isChecked) { buttonView.isChecked = true binding.cbCancelSurveyItem.isChecked = false // binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel) } else { buttonView.isChecked = false binding.cbCancelSurveyItem.isChecked = true // binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel_red) } surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, isChecked) // Log.e("value on cbConfirm", "value : ${surveyData.valueItem}") // Log.e("value survey Item id", "value : ${surveyData.surveyId}") // Log.e("value survey id", "value : ${surveyData.id}") } binding.cbCancelSurveyItem.setOnCheckedChangeListener { buttonView, isChecked -> if (isChecked) { buttonView.isChecked = true binding.cbConfirmSurveyItem.isChecked = false } else { buttonView.isChecked = false binding.cbConfirmSurveyItem.isChecked = true } surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, !isChecked) // // Log.e("value on cbCancel", "value : ${surveyData.valueItem}") // Log.e("value survey Item id", "value : ${surveyData.surveyId}") // Log.e("value survey id", "value : ${surveyData.id}") } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyItemViewHolder { val view = SurveyItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false) return SurveyItemViewHolder(view) } override fun getItemCount(): Int = surveyItemList.size override fun onBindViewHolder(holder: SurveyItemViewHolder, position: Int) { holder.bind(surveyItemList[position], position) } fun setOnValueCallback(onValueClickCallback: SurveyItemListener) { this.surveyItemListener = onValueClickCallback } interface SurveyItemListener { fun onValueChanged(surveyId: String, itemId: String, newValue: Any?) } } </code>
package com.envisions.people.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.envisions.people.R
import com.envisions.people.api.responses.SurveyItem
import com.envisions.people.databinding.SurveyItemLayoutBinding


class SurveyItemAdapter(
    private val surveyItemList: List<SurveyItem>
) :
    RecyclerView.Adapter<SurveyItemAdapter.SurveyItemViewHolder>() {
        private var surveyItemListener : SurveyItemListener? = null
    inner class SurveyItemViewHolder(private val binding: SurveyItemLayoutBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(surveyData: SurveyItem, position: Int) {
            binding.tvSurveyItemTitle.text = "${position + 1}. ${surveyData.name}"

            if (position == itemCount - 1) {
                binding.surveyItemSeparator.visibility = View.GONE
            }

            binding.cbConfirmSurveyItem.setOnCheckedChangeListener { buttonView, isChecked ->
                if (isChecked) {
                    buttonView.isChecked = true
                    binding.cbCancelSurveyItem.isChecked = false
//                    binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel)
                } else {
                    buttonView.isChecked = false
                    binding.cbCancelSurveyItem.isChecked = true
//                    binding.cbCancelSurveyItem.setBackgroundResource(R.drawable.ic_outline_cancel_red)
                }

                surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, isChecked)
//                Log.e("value on cbConfirm", "value : ${surveyData.valueItem}")
//                Log.e("value survey Item id", "value : ${surveyData.surveyId}")
//                Log.e("value survey id", "value : ${surveyData.id}")
            }

            binding.cbCancelSurveyItem.setOnCheckedChangeListener { buttonView, isChecked ->
                if (isChecked) {
                    buttonView.isChecked = true
                    binding.cbConfirmSurveyItem.isChecked = false

                } else {
                    buttonView.isChecked = false
                    binding.cbConfirmSurveyItem.isChecked = true

                }

                surveyItemListener?.onValueChanged(surveyData.surveyId, surveyData.id, !isChecked)
//
//                Log.e("value on cbCancel", "value : ${surveyData.valueItem}")
//                Log.e("value survey Item id", "value : ${surveyData.surveyId}")
//                Log.e("value survey id", "value : ${surveyData.id}")
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SurveyItemViewHolder {
        val view =
            SurveyItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return SurveyItemViewHolder(view)
    }

    override fun getItemCount(): Int = surveyItemList.size

    override fun onBindViewHolder(holder: SurveyItemViewHolder, position: Int) {
        holder.bind(surveyItemList[position], position)
    }

    fun setOnValueCallback(onValueClickCallback: SurveyItemListener) {
        this.surveyItemListener = onValueClickCallback
    }

    interface SurveyItemListener {
        fun onValueChanged(surveyId: String, itemId: String, newValue: Any?)
    }
}

While below is my view model class.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>package com.envisions.people.viewmodels
import android.location.Location
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.envisions.people.api.responses.DataArea
import com.envisions.people.api.responses.DataAssetItem
import com.envisions.people.api.responses.DataLocationItem
import com.envisions.people.api.responses.DataSurvey
import com.envisions.people.data.models.ResultState
import com.envisions.people.data.repository.AreaRepository
import com.envisions.people.data.repository.AssetRepository
import com.envisions.people.data.repository.InspectionRepository
import com.envisions.people.data.repository.LocationRepository
import kotlinx.coroutines.launch
import java.io.File
class CheckInViewModel(
private val locationRepository: LocationRepository?,
private val inspectionRepository: InspectionRepository?,
private val areaRepository: AreaRepository?,
private val assetRepository: AssetRepository?
) : ViewModel() {
var nearestLocation: DataLocationItem? = null
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
private var _error = MutableLiveData<String>()
var errorResponse: LiveData<String> = _error
val surveyItem = MutableLiveData<ArrayList<DataSurvey>>()
private val _areaList = MutableLiveData<ArrayList<DataArea?>?>()
val areaList: LiveData<ArrayList<DataArea?>?> = _areaList
private val _assetList = MutableLiveData<ArrayList<DataAssetItem>>()
val assetList: LiveData<ArrayList<DataAssetItem>> = _assetList
val allAssetsLoaded = MutableLiveData<Boolean>()
// LiveData for etCheckInNotes
val etCheckInNotesLiveData: MutableLiveData<String> = MutableLiveData()
// Combined LiveData for etCheckInNotes and surveyItem
val combinedLiveData: MediatorLiveData<CheckInData> = MediatorLiveData()
init {
combinedLiveData.addSource(surveyItem) { surveyItem ->
val checkInData = CheckInData(etCheckInNotesLiveData.value, surveyItem)
combinedLiveData.value = checkInData
}
combinedLiveData.addSource(etCheckInNotesLiveData) { notes ->
val checkInData = CheckInData(notes, surveyItem.value ?: arrayListOf())
combinedLiveData.value = checkInData
}
}
data class CheckInData(val notes: String?, val surveyItems: ArrayList<DataSurvey>)
fun setLocationViewModel(token: String, currentLat: Double, currentLon: Double) {
allAssetsLoaded.value = false
Log.e("CheckInViewModel", "latitude : $currentLat")
Log.e("CheckInViewModel", "latitude : $currentLon")
viewModelScope.launch {
locationRepository?.setLocation(token)
?.collect { result ->
when (result) {
is ResultState.Loading -> {
// Handle loading state, e.g., show a progress indicator
_isLoading.value = true
}
is ResultState.Success -> {
val locationDataList = result.data.data.toList()
// Access specific location data from locationResponse object
Log.e("CheckInViewModel", locationDataList.toString())
val nearestLocationCheck =
calculateNearestDistance(locationDataList, currentLat, currentLon)
Log.e(
"CheckInViewModel",
"Nearest Location : ${nearestLocationCheck.toString()}"
)
nearestLocation = nearestLocationCheck
getArea(token, nearestLocation?.id.orEmpty())
}
is ResultState.Error -> {
// Handle error, e.g., show Toast or navigate to error screen
// makeToast(context, result.error)
_isLoading.value = false
}
}
}
}
}
fun getArea(token: String, locationId: String) {
var completedAssetCalls = 0
viewModelScope.launch {
areaRepository?.getArea(token, locationId)?.collect { result ->
when (result) {
is ResultState.Loading -> {
// Handle loading state, e.g., show a progress indicator
_isLoading.value = true
}
is ResultState.Success -> {
val currentAreaList = _areaList.value
?: arrayListOf() // Get the current value or create an empty list if null
currentAreaList.addAll(
result.data.data ?: emptyList()
) // Add the new elements
_areaList.value =
currentAreaList // Update the MutableLiveData with the new list
// for (item in result.data.data ?: arrayListOf()) {
// Log.e(TAG, "result.data.data ${result.data.data}")
// _areaList.value?.add(item)
// }
for (area in _areaList.value ?: arrayListOf()) {
getAsset(token, area?.id.orEmpty(), object : FetchCallback {
override fun onDataLoaded() {
completedAssetCalls++
if (completedAssetCalls == _areaList.value?.size) {
allAssetsLoaded.value = true
_isLoading.postValue(false)
}
}
})
}
}
is ResultState.Error -> {
// Handle error, e.g., show Toast or navigate to error screen
// makeToast(context, result.error)
_error.postValue(result.error)
_isLoading.value = false
}
}
}
}
}
fun getAsset(token: String, areaId: String, fetchCallback: FetchCallback) {
viewModelScope.launch {
assetRepository?.getAsset(token, areaId)?.collect { result ->
when (result) {
is ResultState.Loading -> {
// Handle loading state, e.g., show a progress indicator
_isLoading.value = true
}
is ResultState.Success -> {
val currentAssetList = _assetList.value
?: arrayListOf() // Get the current value or create an empty list if null
currentAssetList.addAll(
result.data.data ?: emptyList()
) // Add the new elements
_assetList.value =
currentAssetList // Update the MutableLiveData with the new list
//
// for (item in result.data.data?: arrayListOf()) {
// _assetList.value?.add(item)
// }
fetchCallback.onDataLoaded()
}
is ResultState.Error -> {
// Handle error, e.g., show Toast or navigate to error screen
// makeToast(context, result.error)
_error.postValue(result.error)
_isLoading.value = false
}
}
}
}
}
private fun calculateNearestDistance(
listLocation: List<DataLocationItem>?,
currentLat: Double,
currentLon: Double
): DataLocationItem? {
var nearestLocationItem: DataLocationItem? = null
var nearestDistance = Float.MAX_VALUE
for (itemLocation in listLocation ?: arrayListOf()) {
val result = FloatArray(1)
val (latitudeStr, longitudeStr) = itemLocation.coordinate.split(", ")
Location.distanceBetween(
currentLat,
currentLon,
latitudeStr.toDouble(),
longitudeStr.toDouble(),
result
)
val distance = result[0]
Log.e("CheckInViewModel", "Distance : ${distance.toInt()}, Item : $itemLocation")
if (distance < nearestDistance) {
nearestDistance = distance
nearestLocationItem = itemLocation
}
}
Log.e(
"CheckInViewModel",
"Nearest Distance : ${nearestDistance.toInt()}, Nearest Item : $nearestLocationItem"
)
if (nearestDistance.toInt() > (nearestLocationItem?.radius?.toInt()
?: 500)
) nearestLocationItem = null
return nearestLocationItem
}
fun postCheckIn(
token: String,
notes: String,
locationId: String,
assetId: ArrayList<DataAssetItem>,
fileList: ArrayList<File>,
surveyList: ArrayList<DataSurvey>
) =
inspectionRepository?.postInspection(
token,
notes,
locationId,
assetId,
fileList,
surveyList
)
fun getSurveyGeneral(token: String) {
_isLoading.postValue(true)
viewModelScope.launch {
inspectionRepository?.getSurvey(token, null)?.collect { result ->
when (result) {
is ResultState.Error ->
_error.postValue(result.error)
ResultState.Loading -> _isLoading.postValue(true)
is ResultState.Success -> {
_isLoading.postValue(false)
// _surveyItem.postValue(result.data)
val listSurvey = result.data.data.filter { dataSurvey ->
dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" }
}
surveyItem.postValue(listSurvey as ArrayList<DataSurvey>?)
val arrayTest = ArrayList<Any?>()
surveyItem.value?.forEach { data ->
data.items.forEach { item ->
Log.e(TAG, "item: $item")
arrayTest.add(item.valueItem)
Log.e(TAG, "arraytest : $arrayTest")
}
}
}
}
}
}
}
fun getSurveyAsset(token: String, assetId: String) {
_isLoading.postValue(true)
viewModelScope.launch {
inspectionRepository?.getSurvey(token, assetId)?.collect { result ->
when (result) {
is ResultState.Error ->
_error.postValue(result.error)
ResultState.Loading -> _isLoading.postValue(true)
is ResultState.Success -> {
_isLoading.postValue(false)
// _surveyItem.postValue(result.data)
val listSurvey = result.data.data.filter { dataSurvey ->
dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" }
} as ArrayList<DataSurvey>
val updatedList = ArrayList<DataSurvey>()
surveyItem.value?.forEach { dataSurvey ->
updatedList.add(dataSurvey)
}
// Now, iterate through listSurvey and add elements with unique names
listSurvey.forEach { newSurveyGet ->
val isNew =
updatedList.none { existingSurvey -> existingSurvey.name == newSurveyGet.name }
if (isNew) {
updatedList.add(newSurveyGet)
}
}
surveyItem.postValue(updatedList)
Log.e(TAG, "surveyItem = ${surveyItem.value}")
}
}
}
}
}
fun updateSurveyItemValueItem(surveyId: String, itemId: String, newValue: Any?) {
val updatedList = surveyItem.value?.map { survey ->
if (survey.id == surveyId) {
survey.copy(
items = survey.items.map { item ->
if (item.id == itemId) {
item.copy(valueItem = newValue)
} else {
item
}
}
)
} else {
survey
}
}?.toMutableList()
updatedList?.let { surveyItem.value = it as ArrayList<DataSurvey> }
}
interface FetchCallback {
fun onDataLoaded()
}
companion object {
private const val TAG = "CHECKINVIEWMODEL"
}
}
</code>
<code>package com.envisions.people.viewmodels import android.location.Location import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.envisions.people.api.responses.DataArea import com.envisions.people.api.responses.DataAssetItem import com.envisions.people.api.responses.DataLocationItem import com.envisions.people.api.responses.DataSurvey import com.envisions.people.data.models.ResultState import com.envisions.people.data.repository.AreaRepository import com.envisions.people.data.repository.AssetRepository import com.envisions.people.data.repository.InspectionRepository import com.envisions.people.data.repository.LocationRepository import kotlinx.coroutines.launch import java.io.File class CheckInViewModel( private val locationRepository: LocationRepository?, private val inspectionRepository: InspectionRepository?, private val areaRepository: AreaRepository?, private val assetRepository: AssetRepository? ) : ViewModel() { var nearestLocation: DataLocationItem? = null private val _isLoading = MutableLiveData<Boolean>() val isLoading: LiveData<Boolean> = _isLoading private var _error = MutableLiveData<String>() var errorResponse: LiveData<String> = _error val surveyItem = MutableLiveData<ArrayList<DataSurvey>>() private val _areaList = MutableLiveData<ArrayList<DataArea?>?>() val areaList: LiveData<ArrayList<DataArea?>?> = _areaList private val _assetList = MutableLiveData<ArrayList<DataAssetItem>>() val assetList: LiveData<ArrayList<DataAssetItem>> = _assetList val allAssetsLoaded = MutableLiveData<Boolean>() // LiveData for etCheckInNotes val etCheckInNotesLiveData: MutableLiveData<String> = MutableLiveData() // Combined LiveData for etCheckInNotes and surveyItem val combinedLiveData: MediatorLiveData<CheckInData> = MediatorLiveData() init { combinedLiveData.addSource(surveyItem) { surveyItem -> val checkInData = CheckInData(etCheckInNotesLiveData.value, surveyItem) combinedLiveData.value = checkInData } combinedLiveData.addSource(etCheckInNotesLiveData) { notes -> val checkInData = CheckInData(notes, surveyItem.value ?: arrayListOf()) combinedLiveData.value = checkInData } } data class CheckInData(val notes: String?, val surveyItems: ArrayList<DataSurvey>) fun setLocationViewModel(token: String, currentLat: Double, currentLon: Double) { allAssetsLoaded.value = false Log.e("CheckInViewModel", "latitude : $currentLat") Log.e("CheckInViewModel", "latitude : $currentLon") viewModelScope.launch { locationRepository?.setLocation(token) ?.collect { result -> when (result) { is ResultState.Loading -> { // Handle loading state, e.g., show a progress indicator _isLoading.value = true } is ResultState.Success -> { val locationDataList = result.data.data.toList() // Access specific location data from locationResponse object Log.e("CheckInViewModel", locationDataList.toString()) val nearestLocationCheck = calculateNearestDistance(locationDataList, currentLat, currentLon) Log.e( "CheckInViewModel", "Nearest Location : ${nearestLocationCheck.toString()}" ) nearestLocation = nearestLocationCheck getArea(token, nearestLocation?.id.orEmpty()) } is ResultState.Error -> { // Handle error, e.g., show Toast or navigate to error screen // makeToast(context, result.error) _isLoading.value = false } } } } } fun getArea(token: String, locationId: String) { var completedAssetCalls = 0 viewModelScope.launch { areaRepository?.getArea(token, locationId)?.collect { result -> when (result) { is ResultState.Loading -> { // Handle loading state, e.g., show a progress indicator _isLoading.value = true } is ResultState.Success -> { val currentAreaList = _areaList.value ?: arrayListOf() // Get the current value or create an empty list if null currentAreaList.addAll( result.data.data ?: emptyList() ) // Add the new elements _areaList.value = currentAreaList // Update the MutableLiveData with the new list // for (item in result.data.data ?: arrayListOf()) { // Log.e(TAG, "result.data.data ${result.data.data}") // _areaList.value?.add(item) // } for (area in _areaList.value ?: arrayListOf()) { getAsset(token, area?.id.orEmpty(), object : FetchCallback { override fun onDataLoaded() { completedAssetCalls++ if (completedAssetCalls == _areaList.value?.size) { allAssetsLoaded.value = true _isLoading.postValue(false) } } }) } } is ResultState.Error -> { // Handle error, e.g., show Toast or navigate to error screen // makeToast(context, result.error) _error.postValue(result.error) _isLoading.value = false } } } } } fun getAsset(token: String, areaId: String, fetchCallback: FetchCallback) { viewModelScope.launch { assetRepository?.getAsset(token, areaId)?.collect { result -> when (result) { is ResultState.Loading -> { // Handle loading state, e.g., show a progress indicator _isLoading.value = true } is ResultState.Success -> { val currentAssetList = _assetList.value ?: arrayListOf() // Get the current value or create an empty list if null currentAssetList.addAll( result.data.data ?: emptyList() ) // Add the new elements _assetList.value = currentAssetList // Update the MutableLiveData with the new list // // for (item in result.data.data?: arrayListOf()) { // _assetList.value?.add(item) // } fetchCallback.onDataLoaded() } is ResultState.Error -> { // Handle error, e.g., show Toast or navigate to error screen // makeToast(context, result.error) _error.postValue(result.error) _isLoading.value = false } } } } } private fun calculateNearestDistance( listLocation: List<DataLocationItem>?, currentLat: Double, currentLon: Double ): DataLocationItem? { var nearestLocationItem: DataLocationItem? = null var nearestDistance = Float.MAX_VALUE for (itemLocation in listLocation ?: arrayListOf()) { val result = FloatArray(1) val (latitudeStr, longitudeStr) = itemLocation.coordinate.split(", ") Location.distanceBetween( currentLat, currentLon, latitudeStr.toDouble(), longitudeStr.toDouble(), result ) val distance = result[0] Log.e("CheckInViewModel", "Distance : ${distance.toInt()}, Item : $itemLocation") if (distance < nearestDistance) { nearestDistance = distance nearestLocationItem = itemLocation } } Log.e( "CheckInViewModel", "Nearest Distance : ${nearestDistance.toInt()}, Nearest Item : $nearestLocationItem" ) if (nearestDistance.toInt() > (nearestLocationItem?.radius?.toInt() ?: 500) ) nearestLocationItem = null return nearestLocationItem } fun postCheckIn( token: String, notes: String, locationId: String, assetId: ArrayList<DataAssetItem>, fileList: ArrayList<File>, surveyList: ArrayList<DataSurvey> ) = inspectionRepository?.postInspection( token, notes, locationId, assetId, fileList, surveyList ) fun getSurveyGeneral(token: String) { _isLoading.postValue(true) viewModelScope.launch { inspectionRepository?.getSurvey(token, null)?.collect { result -> when (result) { is ResultState.Error -> _error.postValue(result.error) ResultState.Loading -> _isLoading.postValue(true) is ResultState.Success -> { _isLoading.postValue(false) // _surveyItem.postValue(result.data) val listSurvey = result.data.data.filter { dataSurvey -> dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" } } surveyItem.postValue(listSurvey as ArrayList<DataSurvey>?) val arrayTest = ArrayList<Any?>() surveyItem.value?.forEach { data -> data.items.forEach { item -> Log.e(TAG, "item: $item") arrayTest.add(item.valueItem) Log.e(TAG, "arraytest : $arrayTest") } } } } } } } fun getSurveyAsset(token: String, assetId: String) { _isLoading.postValue(true) viewModelScope.launch { inspectionRepository?.getSurvey(token, assetId)?.collect { result -> when (result) { is ResultState.Error -> _error.postValue(result.error) ResultState.Loading -> _isLoading.postValue(true) is ResultState.Success -> { _isLoading.postValue(false) // _surveyItem.postValue(result.data) val listSurvey = result.data.data.filter { dataSurvey -> dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" } } as ArrayList<DataSurvey> val updatedList = ArrayList<DataSurvey>() surveyItem.value?.forEach { dataSurvey -> updatedList.add(dataSurvey) } // Now, iterate through listSurvey and add elements with unique names listSurvey.forEach { newSurveyGet -> val isNew = updatedList.none { existingSurvey -> existingSurvey.name == newSurveyGet.name } if (isNew) { updatedList.add(newSurveyGet) } } surveyItem.postValue(updatedList) Log.e(TAG, "surveyItem = ${surveyItem.value}") } } } } } fun updateSurveyItemValueItem(surveyId: String, itemId: String, newValue: Any?) { val updatedList = surveyItem.value?.map { survey -> if (survey.id == surveyId) { survey.copy( items = survey.items.map { item -> if (item.id == itemId) { item.copy(valueItem = newValue) } else { item } } ) } else { survey } }?.toMutableList() updatedList?.let { surveyItem.value = it as ArrayList<DataSurvey> } } interface FetchCallback { fun onDataLoaded() } companion object { private const val TAG = "CHECKINVIEWMODEL" } } </code>
package com.envisions.people.viewmodels

import android.location.Location
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.envisions.people.api.responses.DataArea
import com.envisions.people.api.responses.DataAssetItem
import com.envisions.people.api.responses.DataLocationItem
import com.envisions.people.api.responses.DataSurvey
import com.envisions.people.data.models.ResultState
import com.envisions.people.data.repository.AreaRepository
import com.envisions.people.data.repository.AssetRepository
import com.envisions.people.data.repository.InspectionRepository
import com.envisions.people.data.repository.LocationRepository
import kotlinx.coroutines.launch
import java.io.File

class CheckInViewModel(
    private val locationRepository: LocationRepository?,
    private val inspectionRepository: InspectionRepository?,
    private val areaRepository: AreaRepository?,
    private val assetRepository: AssetRepository?
) : ViewModel() {

    var nearestLocation: DataLocationItem? = null

    private val _isLoading = MutableLiveData<Boolean>()
    val isLoading: LiveData<Boolean> = _isLoading

    private var _error = MutableLiveData<String>()
    var errorResponse: LiveData<String> = _error

    val surveyItem = MutableLiveData<ArrayList<DataSurvey>>()

    private val _areaList = MutableLiveData<ArrayList<DataArea?>?>()
    val areaList: LiveData<ArrayList<DataArea?>?> = _areaList

    private val _assetList = MutableLiveData<ArrayList<DataAssetItem>>()
    val assetList: LiveData<ArrayList<DataAssetItem>> = _assetList

    val allAssetsLoaded = MutableLiveData<Boolean>()

    // LiveData for etCheckInNotes
    val etCheckInNotesLiveData: MutableLiveData<String> = MutableLiveData()

    // Combined LiveData for etCheckInNotes and surveyItem
    val combinedLiveData: MediatorLiveData<CheckInData> = MediatorLiveData()

    init {
        combinedLiveData.addSource(surveyItem) { surveyItem ->
            val checkInData = CheckInData(etCheckInNotesLiveData.value, surveyItem)
            combinedLiveData.value = checkInData
        }

        combinedLiveData.addSource(etCheckInNotesLiveData) { notes ->
            val checkInData = CheckInData(notes, surveyItem.value ?: arrayListOf())
            combinedLiveData.value = checkInData
        }
    }


    data class CheckInData(val notes: String?, val surveyItems: ArrayList<DataSurvey>)

    fun setLocationViewModel(token: String, currentLat: Double, currentLon: Double) {
        allAssetsLoaded.value = false

        Log.e("CheckInViewModel", "latitude : $currentLat")
        Log.e("CheckInViewModel", "latitude : $currentLon")
        viewModelScope.launch {
            locationRepository?.setLocation(token)
                ?.collect { result ->
                    when (result) {
                        is ResultState.Loading -> {
                            // Handle loading state, e.g., show a progress indicator
                            _isLoading.value = true
                        }

                        is ResultState.Success -> {
                            val locationDataList = result.data.data.toList()
                            // Access specific location data from locationResponse object
                            Log.e("CheckInViewModel", locationDataList.toString())
                            val nearestLocationCheck =
                                calculateNearestDistance(locationDataList, currentLat, currentLon)
                            Log.e(
                                "CheckInViewModel",
                                "Nearest Location : ${nearestLocationCheck.toString()}"
                            )

                            nearestLocation = nearestLocationCheck
                            getArea(token, nearestLocation?.id.orEmpty())
                        }

                        is ResultState.Error -> {
                            // Handle error, e.g., show Toast or navigate to error screen
//                            makeToast(context, result.error)
                            _isLoading.value = false
                        }
                    }
                }
        }
    }

    fun getArea(token: String, locationId: String) {
        var completedAssetCalls = 0
        viewModelScope.launch {
            areaRepository?.getArea(token, locationId)?.collect { result ->
                when (result) {
                    is ResultState.Loading -> {
                        // Handle loading state, e.g., show a progress indicator
                        _isLoading.value = true
                    }

                    is ResultState.Success -> {
                        val currentAreaList = _areaList.value
                            ?: arrayListOf() // Get the current value or create an empty list if null
                        currentAreaList.addAll(
                            result.data.data ?: emptyList()
                        ) // Add the new elements
                        _areaList.value =
                            currentAreaList // Update the MutableLiveData with the new list


//                        for (item in result.data.data ?: arrayListOf()) {
//                            Log.e(TAG, "result.data.data ${result.data.data}")
//                            _areaList.value?.add(item)
//                        }


                        for (area in _areaList.value ?: arrayListOf()) {
                            getAsset(token, area?.id.orEmpty(), object : FetchCallback {
                                override fun onDataLoaded() {
                                    completedAssetCalls++
                                    if (completedAssetCalls == _areaList.value?.size) {
                                        allAssetsLoaded.value = true
                                        _isLoading.postValue(false)
                                    }
                                }
                            })
                        }
                    }

                    is ResultState.Error -> {
                        // Handle error, e.g., show Toast or navigate to error screen
//                            makeToast(context, result.error)
                        _error.postValue(result.error)
                        _isLoading.value = false
                    }
                }
            }
        }
    }

    fun getAsset(token: String, areaId: String, fetchCallback: FetchCallback) {
        viewModelScope.launch {
            assetRepository?.getAsset(token, areaId)?.collect { result ->
                when (result) {
                    is ResultState.Loading -> {
                        // Handle loading state, e.g., show a progress indicator
                        _isLoading.value = true
                    }

                    is ResultState.Success -> {

                        val currentAssetList = _assetList.value
                            ?: arrayListOf() // Get the current value or create an empty list if null
                        currentAssetList.addAll(
                            result.data.data ?: emptyList()
                        ) // Add the new elements
                        _assetList.value =
                            currentAssetList // Update the MutableLiveData with the new list
//
//                        for (item in result.data.data?: arrayListOf()) {
//                            _assetList.value?.add(item)
//                        }

                        fetchCallback.onDataLoaded()
                    }

                    is ResultState.Error -> {
                        // Handle error, e.g., show Toast or navigate to error screen
//                            makeToast(context, result.error)
                        _error.postValue(result.error)
                        _isLoading.value = false
                    }
                }
            }
        }
    }


    private fun calculateNearestDistance(
        listLocation: List<DataLocationItem>?,
        currentLat: Double,
        currentLon: Double
    ): DataLocationItem? {
        var nearestLocationItem: DataLocationItem? = null
        var nearestDistance = Float.MAX_VALUE

        for (itemLocation in listLocation ?: arrayListOf()) {
            val result = FloatArray(1)
            val (latitudeStr, longitudeStr) = itemLocation.coordinate.split(", ")
            Location.distanceBetween(
                currentLat,
                currentLon,
                latitudeStr.toDouble(),
                longitudeStr.toDouble(),
                result
            )
            val distance = result[0]
            Log.e("CheckInViewModel", "Distance :  ${distance.toInt()}, Item : $itemLocation")
            if (distance < nearestDistance) {
                nearestDistance = distance
                nearestLocationItem = itemLocation
            }
        }

        Log.e(
            "CheckInViewModel",
            "Nearest Distance :  ${nearestDistance.toInt()}, Nearest Item : $nearestLocationItem"
        )

        if (nearestDistance.toInt() > (nearestLocationItem?.radius?.toInt()
                ?: 500)
        ) nearestLocationItem = null

        return nearestLocationItem
    }

    fun postCheckIn(
        token: String,
        notes: String,
        locationId: String,
        assetId: ArrayList<DataAssetItem>,
        fileList: ArrayList<File>,
        surveyList: ArrayList<DataSurvey>
    ) =
        inspectionRepository?.postInspection(
            token,
            notes,
            locationId,
            assetId,
            fileList,
            surveyList
        )

    fun getSurveyGeneral(token: String) {
        _isLoading.postValue(true)
        viewModelScope.launch {
            inspectionRepository?.getSurvey(token, null)?.collect { result ->
                when (result) {
                    is ResultState.Error ->
                        _error.postValue(result.error)

                    ResultState.Loading -> _isLoading.postValue(true)
                    is ResultState.Success -> {
                        _isLoading.postValue(false)
//                        _surveyItem.postValue(result.data)

                        val listSurvey = result.data.data.filter { dataSurvey ->
                            dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" }
                        }

                        surveyItem.postValue(listSurvey as ArrayList<DataSurvey>?)
                        val arrayTest = ArrayList<Any?>()
                        surveyItem.value?.forEach { data ->
                            data.items.forEach { item ->
                                Log.e(TAG, "item: $item")
                                arrayTest.add(item.valueItem)
                                Log.e(TAG, "arraytest : $arrayTest")
                            }
                        }
                    }
                }
            }
        }
    }

    fun getSurveyAsset(token: String, assetId: String) {
        _isLoading.postValue(true)
        viewModelScope.launch {
            inspectionRepository?.getSurvey(token, assetId)?.collect { result ->
                when (result) {
                    is ResultState.Error ->
                        _error.postValue(result.error)

                    ResultState.Loading -> _isLoading.postValue(true)
                    is ResultState.Success -> {
                        _isLoading.postValue(false)
//                        _surveyItem.postValue(result.data)

                        val listSurvey = result.data.data.filter { dataSurvey ->
                            dataSurvey.items.any { surveyItem -> surveyItem.type.name == "checklist" }
                        } as ArrayList<DataSurvey>

                        val updatedList = ArrayList<DataSurvey>()

                        surveyItem.value?.forEach { dataSurvey ->
                            updatedList.add(dataSurvey)
                        }

                        // Now, iterate through listSurvey and add elements with unique names
                        listSurvey.forEach { newSurveyGet ->
                            val isNew =
                                updatedList.none { existingSurvey -> existingSurvey.name == newSurveyGet.name }
                            if (isNew) {
                                updatedList.add(newSurveyGet)
                            }
                        }

                        surveyItem.postValue(updatedList)
                        Log.e(TAG, "surveyItem = ${surveyItem.value}")
                    }
                }
            }
        }
    }

    fun updateSurveyItemValueItem(surveyId: String, itemId: String, newValue: Any?) {
        val updatedList = surveyItem.value?.map { survey ->
            if (survey.id == surveyId) {
                survey.copy(
                    items = survey.items.map { item ->
                        if (item.id == itemId) {
                            item.copy(valueItem = newValue)
                        } else {
                            item
                        }
                    }
                )
            } else {
                survey
            }
        }?.toMutableList()

        updatedList?.let { surveyItem.value = it as ArrayList<DataSurvey> }
    }

    interface FetchCallback {
        fun onDataLoaded()
    }

    companion object {
        private const val TAG = "CHECKINVIEWMODEL"
    }

}

And finally this is my implementation in the activity class.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>checkInViewModel.surveyItem.observe(this) { surveyData ->
if (surveyData.isNotEmpty()) {
surveyAdapter = SurveyContainerAdapter(checkInViewModel.surveyItem.value ?: arrayListOf(), this)
binding.rvSurveyInspection.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rvSurveyInspection.adapter = surveyAdapter
surveyAdapter.setOnItemClickCallback(object :
SurveyContainerAdapter.OnItemClickCallback {
override fun onItemClicked(data: DataSurvey, position: Int) {
if (position != -1) {
updateSurvey(position)
}
val foundAsset : ArrayList<DataAssetItem> = arrayListOf()
assetList.forEachIndexed { _, dataAssetItem ->
data.assets.forEach { assetsItem ->
if(assetsItem.assetId == dataAssetItem.id){
foundAsset.add(dataAssetItem)
return@forEachIndexed
}
}
}
if(foundAsset.isNotEmpty()){
foundAsset.forEach { assetItem ->
val foundAssetIndex = assetList.indexOf(assetItem)
assetList.removeAt(foundAssetIndex)
assetAdapter.notifyItemRemoved(foundAssetIndex)
assetAdapter.notifyItemRangeChanged(
foundAssetIndex,
assetList.size.minus(foundAssetIndex)
)
}
}
}
override fun onValueClicked(surveyId: String, itemId: String, newValue: Any?) {
checkInViewModel.updateSurveyItemValueItem(surveyId, itemId, newValue)
}
})
}
surveyData.forEach { dataSurvey ->
Log.e(TAG, "test $dataSurvey")
}
}
</code>
<code>checkInViewModel.surveyItem.observe(this) { surveyData -> if (surveyData.isNotEmpty()) { surveyAdapter = SurveyContainerAdapter(checkInViewModel.surveyItem.value ?: arrayListOf(), this) binding.rvSurveyInspection.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) binding.rvSurveyInspection.adapter = surveyAdapter surveyAdapter.setOnItemClickCallback(object : SurveyContainerAdapter.OnItemClickCallback { override fun onItemClicked(data: DataSurvey, position: Int) { if (position != -1) { updateSurvey(position) } val foundAsset : ArrayList<DataAssetItem> = arrayListOf() assetList.forEachIndexed { _, dataAssetItem -> data.assets.forEach { assetsItem -> if(assetsItem.assetId == dataAssetItem.id){ foundAsset.add(dataAssetItem) return@forEachIndexed } } } if(foundAsset.isNotEmpty()){ foundAsset.forEach { assetItem -> val foundAssetIndex = assetList.indexOf(assetItem) assetList.removeAt(foundAssetIndex) assetAdapter.notifyItemRemoved(foundAssetIndex) assetAdapter.notifyItemRangeChanged( foundAssetIndex, assetList.size.minus(foundAssetIndex) ) } } } override fun onValueClicked(surveyId: String, itemId: String, newValue: Any?) { checkInViewModel.updateSurveyItemValueItem(surveyId, itemId, newValue) } }) } surveyData.forEach { dataSurvey -> Log.e(TAG, "test $dataSurvey") } } </code>
checkInViewModel.surveyItem.observe(this) { surveyData ->
            if (surveyData.isNotEmpty()) {
                surveyAdapter = SurveyContainerAdapter(checkInViewModel.surveyItem.value ?: arrayListOf(), this)
                binding.rvSurveyInspection.layoutManager =
                    LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
                binding.rvSurveyInspection.adapter = surveyAdapter

                surveyAdapter.setOnItemClickCallback(object :
                    SurveyContainerAdapter.OnItemClickCallback {
                    override fun onItemClicked(data: DataSurvey, position: Int) {
                        if (position != -1) {
                            updateSurvey(position)
                        }

                        val foundAsset : ArrayList<DataAssetItem> = arrayListOf()

                        assetList.forEachIndexed { _, dataAssetItem ->
                            data.assets.forEach { assetsItem ->
                                if(assetsItem.assetId == dataAssetItem.id){
                                    foundAsset.add(dataAssetItem)
                                    return@forEachIndexed
                                }
                            }
                        }

                        if(foundAsset.isNotEmpty()){
                            foundAsset.forEach { assetItem ->
                                val foundAssetIndex = assetList.indexOf(assetItem)
                                assetList.removeAt(foundAssetIndex)
                                assetAdapter.notifyItemRemoved(foundAssetIndex)
                                assetAdapter.notifyItemRangeChanged(
                                    foundAssetIndex,
                                    assetList.size.minus(foundAssetIndex)
                                )
                            }
                        }
                    }

                    override fun onValueClicked(surveyId: String, itemId: String, newValue: Any?) {
                        checkInViewModel.updateSurveyItemValueItem(surveyId, itemId, newValue)
                    }
                })
            }

            surveyData.forEach { dataSurvey ->
                Log.e(TAG, "test $dataSurvey")
            }
        }

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật