Back-end (JVM) Internal error: Failed to generate expression: KtBlockExpression - kotlin

My code is working but my test is not working when I use the deprecated version of kotlin 1.3. When I change the version to 1.6 the test class works normally. The problem is that all the code in my project's modules is still at version 1.3 and all the code is still working. What do I need to change to get my code past kotlin version 1.3?
Error on console:
Kotlin: [Internal Error] org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Failed to generate expression: KtBlockExpression
The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$typeMappingConfiguration$1.processErrorType(KotlinTypeMapper.kt:127)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:355)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:454)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:411)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1839)
at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$FunctionDefault.doGenerateBody(FunctionGenerationStrategy.java:64)
at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:86)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:646)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:483)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:260)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:165)
at org.jetbrains.kotlin.codegen.FunctionCodegen.gen(FunctionCodegen.java:136)
at org.jetbrains.kotlin.codegen.MemberCodegen.genSimpleMember(MemberCodegen.java:200)
at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateDeclaration(ClassBodyCodegen.java:170)
at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBody(ClassBodyCodegen.java:88)
at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:132)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:305)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:289)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassesAndObjectsInFile(PackageCodegenImpl.java:119)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:138)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:70)
at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generatePackage(CodegenFactory.kt:140)
at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.invokeLowerings(CodegenFactory.kt:119)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runLowerings(KotlinToJVMBytecodeCompiler.kt:373)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:129)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:60)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:172)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:54)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:91)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:43)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:93)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1547)
at jdk.internal.reflect.GeneratedMethodAccessor123.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalStateException: Error type encountered: (org.jetbrains.kotlin.types.ErrorUtils$UninferredParameterTypeConstructor#d084bd5..org.jetbrains.kotlin.types.ErrorUtils$UninferredParameterTypeConstructor#d084bd5) (FlexibleTypeImpl).
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$typeMappingConfiguration$1.processErrorType(KotlinTypeMapper.kt:127)
at org.jetbrains.kotlin.load.kotlin.DescriptorBasedTypeSignatureMappingKt.mapType(descriptorBasedTypeSignatureMapping.kt:81)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.mapType(KotlinTypeMapper.kt:279)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$writeGenericArguments$1$1.invoke(KotlinTypeMapper.kt:370)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$writeGenericArguments$1$1.invoke(KotlinTypeMapper.kt:369)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$Companion.writeGenericArguments(KotlinTypeMapper.kt:1502)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.writeGenericArguments(KotlinTypeMapper.kt:369)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.writeGenericArguments(KotlinTypeMapper.kt:359)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.writeGenericType(KotlinTypeMapper.kt:312)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.access$writeGenericType(KotlinTypeMapper.kt:84)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$mapType$1.invoke(KotlinTypeMapper.kt:282)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper$mapType$1.invoke(KotlinTypeMapper.kt:279)
at org.jetbrains.kotlin.load.kotlin.DescriptorBasedTypeSignatureMappingKt.mapType(descriptorBasedTypeSignatureMapping.kt:54)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.mapType(KotlinTypeMapper.kt:279)
at org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.mapTypeArgument(KotlinTypeMapper.kt:229)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.getOrCreateCallGenerator(ExpressionCodegen.java:2945)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.getOrCreateCallGenerator(ExpressionCodegen.java:2926)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2691)
at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:42)
at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:41)
at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:68)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:128)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:121)
at org.jetbrains.kotlin.codegen.CallReceiver.putSelector(CallReceiver.java:168)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:128)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:121)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.putReceiverAndInlineMarkerIfNeeded(ExpressionCodegen.java:2812)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2720)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2700)
at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:42)
at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:41)
at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:68)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:128)
at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:121)
at org.jetbra
ins.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1341)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1280)
at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:56)
at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:22)
at org.jetbrains.kotlin.psi.KtBlockExpression.accept(KtBlockExpression.java:79)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:333)
... 46 more```
And here my unit test
And my code below, the error happens in my setup function
```#ExtendWith(MockitoExtension::class)
class ServiceTest {
private val reasonRepository: ReasonRepository = mock()
private val productRepository: ProductRepository = mock()
private val productTagRepository: ProductTagRepository = mock()
private val partnerRepository: PartnerRepository = mock()
private val productService: ProductService = mock()
private val loanRepository: LoanRepository = mock()
private val financialProductTagRepository: FinancialProductTagRepository = mock()
private lateinit var strategyOne: StrategyOne
private lateinit var strategyTwo: StrategyTwo
private lateinit var strategyThree: StrategyThree
private lateinit var strategyFour: StrategyFour
private lateinit var strategyFive: StrategyFive
private lateinit var strategySix: StrategySix
private lateinit var strategySeven: StrategySeven
private lateinit var service: Service
private lateinit var strategy: List<Strategy>
private lateinit var serviceHelper: ServiceHelper
companion object {
private val loanTypeLow = BigDecimal(2000)
private val loanTypeMedium = BigDecimal(2001)
private val loanTypeHigh = BigDecimal(100001)
}
#BeforeEach
fun setUp() {
serviceHelper = ServiceHelper(productRepository, productService)
strategyOne = StrategyOne(serviceHelper)
strategyTwo = StrategyTwo(serviceHelper)
strategyThree = StrategyThree(serviceHelper)
strategyFour = StrategyFour(serviceHelper)
strategyFive = StrategyFive(serviceHelper)
strategySix = StrategySix(serviceHelper)
strategySeven = StrategySeven(serviceHelper)
strategy =
listOf(
strategyOne,
strategyTwo,
strategyThree,
strategyFour,
strategyFive,
strategySix,
strategySeven
)
service = Service(Strategy, serviceHelper, reasonRepository)
val loanOne = Loan(
id = 1,
name = LoanType.LOW
)
val loanTwo = Loan(
id = 2,
name = LoanType.MEDIUM
)
val loanThree = Loan(
id = 3,
name = LoanType.HIGH
)
val reasonOne = Reason(
id = 1,
title = "Bar 1",
type = FINANCING,
loan = setOf(loanThree),
index = 1
)
val reasonTwo = Reason(
id = 2,
title = "Bar 2",
type = FINANCING,
loan = setOf(loanThree),
index = 2
)
val reasonThree = Reason(
id = 3,
title = "Bar 3",
type = FINANCING,
loan = setOf(loanTwo, loanThree),
index = 4
)
val reasonFour = Reason(
id = 4,
title = "Bar 4",
type = FINANCING,
loan = setOf(loanTwo, loanThree),
index = 3
)
val reasonFive = Reason(
id = 5,
title = "Bar 5",
type = OTHER,
loan = setOf(loanTwo)
)
val reasonSix = Reason(
id = 6,
title = "Bar 6",
type = OTHER,
loan = setOf(loanTwo)
)
val reasonSeven = Reason(
id = 7,
title = "Outro",
type = OTHER,
loan = setOf(loanTwo, loanThree),
index = 5
)
val tag = ProductTag(
id = 1,
title = "Foo 1",
description = "tag 1",
icon = "icone 1",
weight = 98
)
val partner = Partner(
id = 1,
name = "Foo 1",
description = "partner 1",
link = "link.com",
logo = "logo.png",
contactType = "",
buttonLabel = ""
)
val partnerDto = PartnerDto(
id = partner.id,
name = partner.name,
description = partner.description,
logo = partner.logo,
link = partner.link,
action = Action("", "", "")
)
val productTagDto = ProductTagDto(
id = tag.id,
title = tag.title,
description = tag.description,
icon = tag.icon,
iconWhite = tag.iconWhite,
iconOrange = tag.iconOrange,
weight = tag.weight,
highlight = true
)
val productOne = FinancialProduct(
id = 1,
title = "Foo 1",
description = "Product 1",
partners = setOf(partner),
loan = setOf(loanTwo, loanThree),
index = 4,
category = PERSONAL_LOAN
)
val productOneDto = FinancialProductDto(
id = productOne.id,
title = productOne.title,
description = productOne.description,
category = productOne.category,
tags = listOf(productTagDto),
partners = setOf(partnerDto)
)
val productTwo = FinancialProduct(
id = 2,
title = "Foo 2",
description = "Product 2",
partners = setOf(partner),
loan = setOf(loanTwo, loanThree),
index = 1,
category = TRUCK_SECURED_LOAN
)
val productTwoDto = FinancialProductDto(
id = productTwo.id,
title = productTwo.title,
description = productTwo.description,
partners = setOf(partnerDto),
category = TRUCK_SECURED_LOAN,
tags = listOf(productTagDto)
)
val productThree = FinancialProduct(
id = 3,
title = "Foo 3",
description = "Product 3",
partners = setOf(partner),
loan = setOf(loanTwo, loanThree),
index = 2,
category = CAR_SECURED_LOAN
)
val productThreeDto = FinancialProductDto(
id = productThree.id,
title = productThree.title,
description = productThree.description,
partners = setOf(partnerDto),
category = CAR_SECURED_LOAN,
tags = listOf(productTagDto)
)
val productFour = FinancialProduct(
id = 4,
title = "Foo 4",
description = "Product 4",
partners = setOf(partner),
loan = setOf(loanThree),
index = 3,
category = TRUCK_FINANCING
)
val productFourDto = FinancialProductDto(
id = productFour.id,
title = productFour.title,
description = productFour.description,
partners = setOf(partnerDto),
category = TRUCK_FINANCING,
tags = listOf(productTagDto)
)
val productFive = FinancialProduct(
id = 5,
title = "Foo 5",
description = "Product 5",
partners = setOf(),
loan = setOf(),
category = NOT_AVAILABLE
)
val productFiveDto = FinancialProductDto(
id = productFive.id,
title = productFive.title,
description = productFive.description,
category = NOT_AVAILABLE,
tags = listOf(productTagDto),
partners = setOf(partnerDto)
)
val productSix = FinancialProduct(
id = 6,
title = "Foo 6",
description = "Product 6",
partners = setOf(),
loan = setOf(),
category = NOT_AVAILABLE
)
val productSixDto = FinancialProductDto(
id = productSix.id,
title = productSix.title,
description = productSix.description,
partners = setOf(partnerDto),
category = NOT_AVAILABLE,
tags = listOf(productTagDto)
)
val financialProductOneTag = FinancialProductTag(
id = 1L,
financialProduct = productOne,
productTag = tag,
highlight = true
)
val financialProductTwoTag = FinancialProductTag(
id = 2L,
financialProduct = productTwo,
productTag = tag,
highlight = true
)
val financialProductThreeTag = FinancialProductTag(
id = 3L,
financialProduct = productThree,
productTag = tag,
highlight = true
)
val financialProductFourTag = FinancialProductTag(
id = 4L,
financialProduct = productFour,
productTag = tag,
highlight = true
)
whenever(loanRepository.saveAll(listOf(any()))).thenReturn(listOf(loanOne, loanTwo, loanThree))
whenever(loanRepository.findAll()).thenReturn(listOf(loanOne, loanTwo, loanThree))
whenever(reasonRepository.saveAll(listOf(any()))).thenReturn(
listOf(
reasonOne,
reasonTwo,
reasonThree,
reasonFour,
reasonFive,
reasonSix,
reasonSeven
)
)
whenever(reasonRepository.findAll()).thenReturn(
listOf(
reasonOne,
reasonTwo,
reasonThree,
reasonFour,
reasonFive,
reasonSix,
reasonSeven
)
)
whenever(productTagRepository.saveAll(listOf(any()))).thenReturn(listOf(tag))
whenever(partnerRepository.saveAll(listOf(any()))).thenReturn(listOf(partner))
whenever(financialProductRepository.saveAll(listOf(any()))).thenReturn(
listOf(
productOne,
productTwo,
productThree,
productFour,
productFive,
productSix
)
)
whenever(financialProductTagRepository.saveAll(listOf(any()))).thenReturn(
listOf(
financialProductOneTag,
financialProductTwoTag,
financialProductThreeTag,
financialProductFourTag
)
)
whenever(financialProductRepository.findAll()).thenReturn(
listOf(
productOne,
productTwo,
productThree,
productFour,
productFive,
productSix
)
)
whenever(financialProductService.mapTagToDtoBeta(any())).thenReturn(listOf(productTagDto))
whenever(financialProductService.mapPartnerToDto(any())).thenReturn(setOf(partnerDto))
whenever(
financialProductService.mapFinancialProductToDto(
productOne,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productOneDto)
whenever(
financialProductService.mapFinancialProductToDto(
productTwo,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productTwoDto)
whenever(
financialProductService.mapFinancialProductToDto(
productThree,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productThreeDto)
whenever(
financialProductService.mapFinancialProductToDto(
productFour,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productFourDto)
whenever(
financialProductService.mapFinancialProductToDto(
productFive,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productFiveDto)
whenever(
financialProductService.mapFinancialProductToDto(
productSix,
listOf(productTagDto),
setOf(partnerDto)
)
).thenReturn(productSixDto)
}```

Related

Jetpack Compose interface is never updated with new api data

I'm making my first app with Kotlin and Jetpack Compose, I’m still studying. The app, It is a meteorological application that takes the data from an API. The MainScreen starts with the data of the city of Madrid by default, and has a searchBar where you can search for any other city. My problem is that when a new city is introduced in the searchbar, this name travels to the backend and makes the calls to the API, the API responds with the new data but these never come back to the interface. The MainScreen is never updated with new data, but I can see the data on my console.
Any help in welcome, thanks in advance
MainScreen
#RequiresApi(Build.VERSION_CODES.O)
#SuppressLint("UnusedMaterialScaffoldPaddingParameter", "SimpleDateFormat")
#Composable
fun MainScreen(
MainViewModel: MainViewModel
) {
val acceso = Accesso_API()
acceso.coger_tiempo_nombre("Madrid")
while (!acceso.datos_adquiridos) {}
Log.println(Log.ASSERT, "Inicio MainScreen", acceso.resultado.toString())
Surface(
color = MaterialTheme.colors.background,
modifier = Modifier
.fillMaxHeight()
.fillMaxSize()
) {
val searchWidgetState by MainViewModel.searchWidgetState
val searchTextState by MainViewModel.searchTextState
Scaffold(
modifier = Modifier
.fillMaxSize(),
topBar = {
MainAppBar(
searchWidgetState = searchWidgetState,
searchTextState = searchTextState,
onTextChange = {
MainViewModel.updateSearchTextState(newValue = it)
},
onCloseClicked = {
MainViewModel.updateSearchWidgetState(newValue = SearchWidgetState.CLOSED)
},
onSearchClicked = {
Log.d("Searched Text", it)
MainViewModel.searchTextState.value
Log.d("searchTextState", searchTextState)
acceso.coger_tiempo_nombre(searchTextState)
},
onSearchTriggered = {
MainViewModel.updateSearchWidgetState(newValue = SearchWidgetState.OPENED)
}
)
}
) {
Column(
modifier = Modifier
.background(Color.White)
.fillMaxWidth()
.padding(20.dp)
.verticalScroll(rememberScrollState())
) {
//TARJETA PRICIPAL
Card(
modifier = Modifier
.fillMaxWidth(),
backgroundColor = GreyCard,
elevation = 0.dp,
shape = RoundedCornerShape(10.dp)
) {
WeatherDisplayDailyCard(acceso.resultado)
}
//DETALLES
Row(
modifier = Modifier
.padding(
top = 5.dp,
bottom = 0.dp
)
.align(Alignment.CenterHorizontally),
horizontalArrangement = Arrangement.SpaceBetween,
) {
DetailsItem(
details = WeatherDetails(
units = "Pressure",
data = "${acceso.resultado.presion.toString()} mb",
R.drawable.pressure,
color = GreyCard
)
)
DetailsItem(
details = WeatherDetails(
units = "Wind",
data = "${acceso.resultado.viento.toString()} km/h",
R.drawable.wind2,
color = GreyCard
)
)
}
Row(
modifier = Modifier
.padding(
top = 0.dp,
bottom = 0.dp
)
.align(Alignment.CenterHorizontally),
horizontalArrangement = Arrangement.SpaceBetween,
) {
DetailsItem(
details = WeatherDetails(
units = "UV Index",
data = acceso.resultado.uv_text.toString(),
R.drawable.rays,
color = GreyCard
)
)
DetailsItem(
details = WeatherDetails(
units = "Humidity",
data = "${acceso.resultado.humedad_relativa.toString()} %",
R.drawable.water,
color = GreyCard
)
)
}
Spacer(modifier = Modifier.height(16.dp))
//12 HORAS
var hour_1 = acceso.resultado.hora_1;
var hour_2 = acceso.resultado.hora_2;
var hour_3 = acceso.resultado.hora_3;
var hour_4 = acceso.resultado.hora_4;
var hour_5 = acceso.resultado.hora_5;
var hour_6 = acceso.resultado.hora_6;
var hour_7 = acceso.resultado.hora_7;
var hour_8 = acceso.resultado.hora_8;
var hour_9 = acceso.resultado.hora_9;
var hour_10 = acceso.resultado.hora_10;
var hour_11 = acceso.resultado.hora_11;
var hour_12 = acceso.resultado.hora_12;
val formatterHour = DateTimeFormatter.ISO_DATE_TIME
val time1: LocalTime? = LocalTime.parse(hour_1, formatterHour)
val time2: LocalTime? = LocalTime.parse(hour_2, formatterHour)
val time3: LocalTime? = LocalTime.parse(hour_3, formatterHour)
val time4: LocalTime? = LocalTime.parse(hour_4, formatterHour)
val time5: LocalTime? = LocalTime.parse(hour_5, formatterHour)
val time6: LocalTime? = LocalTime.parse(hour_6, formatterHour)
val time7: LocalTime? = LocalTime.parse(hour_7, formatterHour)
val time8: LocalTime? = LocalTime.parse(hour_8, formatterHour)
val time9: LocalTime? = LocalTime.parse(hour_9, formatterHour)
val time10: LocalTime? = LocalTime.parse(hour_10, formatterHour)
val time11: LocalTime? = LocalTime.parse(hour_11, formatterHour)
val time12: LocalTime? = LocalTime.parse(hour_12, formatterHour)
HourlyForecastSheet(
hourlyForecast = listOf(
HourlyDetails(
hour = time1.toString(),
icon = acceso.resultado.icono_hora_1,
temperature = acceso.resultado.temperatura_hora_1
),
HourlyDetails(
hour = time2.toString(),
icon = acceso.resultado.icono_hora_2,
temperature = acceso.resultado.temperatura_hora_2
),
HourlyDetails(
hour = time3.toString(),
icon = acceso.resultado.icono_hora_3,
temperature = acceso.resultado.temperatura_hora_3
),
HourlyDetails(
hour = time4.toString(),
icon = acceso.resultado.icono_hora_4,
temperature = acceso.resultado.temperatura_hora_4
),
HourlyDetails(
hour = time5.toString(),
icon = acceso.resultado.icono_hora_5,
temperature = acceso.resultado.temperatura_hora_5
),
HourlyDetails(
hour = time6.toString(),
icon = acceso.resultado.icono_hora_6,
temperature = acceso.resultado.temperatura_hora_6
),
HourlyDetails(
hour = time7.toString(),
icon = acceso.resultado.icono_hora_7,
temperature = acceso.resultado.temperatura_hora_7
),
HourlyDetails(
hour = time8.toString(),
icon = acceso.resultado.icono_hora_8,
temperature = acceso.resultado.temperatura_hora_8
),
HourlyDetails(
hour = time9.toString(),
icon = acceso.resultado.icono_hora_9,
temperature = acceso.resultado.temperatura_hora_9
),
HourlyDetails(
hour = time10.toString(),
icon = acceso.resultado.icono_hora_10,
temperature = acceso.resultado.temperatura_hora_10
),
HourlyDetails(
hour = time11.toString(),
icon = acceso.resultado.icono_hora_11,
temperature = acceso.resultado.temperatura_hora_11
),
HourlyDetails(
hour = time12.toString(),
icon = acceso.resultado.icono_hora_12,
temperature = acceso.resultado.temperatura_hora_12
),
)
)
Spacer(modifier = Modifier.height(8.dp))
//5 DIAS
Column()
{
val date_1 = acceso.resultado.fecha_dia_1
val date_2 = acceso.resultado.fecha_dia_2
val date_3 = acceso.resultado.fecha_dia_3
val date_4 = acceso.resultado.fecha_dia_4
val date_5 = acceso.resultado.fecha_dia_5
val formatterDate = DateTimeFormatter.ISO_DATE_TIME
val day_1: OffsetDateTime = OffsetDateTime.parse(date_1, formatterDate)
val day_2: OffsetDateTime = OffsetDateTime.parse(date_2, formatterDate)
val day_3: OffsetDateTime = OffsetDateTime.parse(date_3, formatterDate)
val day_4: OffsetDateTime = OffsetDateTime.parse(date_4, formatterDate)
val day_5: OffsetDateTime = OffsetDateTime.parse(date_5, formatterDate)
val date1: DayOfWeek? = LocalDate.from(day_1).dayOfWeek
val date2: DayOfWeek? = LocalDate.from(day_2).dayOfWeek
val date3: DayOfWeek? = LocalDate.from(day_3).dayOfWeek
val date4: DayOfWeek? = LocalDate.from(day_4).dayOfWeek
val date5: DayOfWeek? = LocalDate.from(day_5).dayOfWeek
Next5daysForecastItem(
Next5daysForecast(
date_5days = date1.toString(),
icon_5days = acceso.resultado.icono_dia_1,
temperature_min_5days = acceso.resultado.Temp_min_dia_1,
temperature_max_5days = acceso.resultado.Temp_max_dia_1,
icon_frase_5days = acceso.resultado.frase_dia_1,
)
)
Next5daysForecastItem(
Next5daysForecast(
date_5days = date2.toString(),
icon_5days = acceso.resultado.icono_dia_2,
temperature_min_5days = acceso.resultado.Temp_min_dia_2,
temperature_max_5days = acceso.resultado.Temp_max_dia_2,
icon_frase_5days = acceso.resultado.frase_dia_2,
)
)
Next5daysForecastItem(
Next5daysForecast(
date_5days = date3.toString(),
icon_5days = acceso.resultado.icono_dia_3,
temperature_min_5days = acceso.resultado.Temp_min_dia_3,
temperature_max_5days = acceso.resultado.Temp_max_dia_3,
icon_frase_5days = acceso.resultado.frase_dia_3,
)
)
Next5daysForecastItem(
Next5daysForecast(
date_5days = date4.toString(),
icon_5days = acceso.resultado.icono_dia_4,
temperature_min_5days = acceso.resultado.Temp_min_dia_4,
temperature_max_5days = acceso.resultado.Temp_max_dia_4,
icon_frase_5days = acceso.resultado.frase_dia_4,
)
)
Next5daysForecastItem(
Next5daysForecast(
date_5days = date5.toString(),
icon_5days = acceso.resultado.icono_dia_5,
temperature_min_5days = acceso.resultado.Temp_min_dia_5,
temperature_max_5days = acceso.resultado.Temp_max_dia_5,
icon_frase_5days = acceso.resultado.frase_dia_5,
)
)
Log.println(Log.ASSERT, "Final MainScreen", acceso.resultado.toString())
}
}
}
}
}
MainViewModel
#RequiresApi(Build.VERSION_CODES.O)
class MainViewModel : ViewModel() {
private val _searchWidgetState: MutableState<SearchWidgetState> =
mutableStateOf(value = SearchWidgetState.CLOSED)
val searchWidgetState: State<SearchWidgetState> = _searchWidgetState
private val _searchTextState: MutableState<String> =
mutableStateOf(value = "")
val searchTextState: State<String> = _searchTextState
fun updateSearchWidgetState(newValue: SearchWidgetState) {
_searchWidgetState.value = newValue
}
fun updateSearchTextState(newValue: String) {
_searchTextState.value = newValue
}
}
API_Access
class Accesso_API {
val api_key ="87EYQdAb8jlViEELJJ6KsgJGfkcKG6qu"
#RequiresApi(Build.VERSION_CODES.O)
var resultado: Datos_Tiempo = Datos_Tiempo()
var datos_adquiridos: Boolean = false
#RequiresApi(Build.VERSION_CODES.O)
fun coger_tiempo_posicion_gps(longitud: Float, latitud: Float) {
coger_datos("", longitud,latitud,"")
}
#RequiresApi(Build.VERSION_CODES.O)
fun coger_tiempo_nombre(
nombre: String,
) {
coger_datos(nombre, 0.0f,0.0f,"")
}
#RequiresApi(Build.VERSION_CODES.O)
fun coger_tiempo_key(key: String) {
coger_datos("", 0.0f,0.0f,key)
}
#RequiresApi(Build.VERSION_CODES.O)
private fun coger_datos(nombre: String, longitud: Float, latitud: Float, p_key: String) {
datos_adquiridos = false
val quotesApi = RetrofitHelper.getInstance().create(QuotesApi_Tiempo::class.java)
// launching a new coroutine
GlobalScope.launch {
var key = "308526"
var ciudad_texto = "Sevilla"
Log.println(Log.ASSERT, "", "Ciudad entregada:" + nombre)
if (nombre != "") {
Log.println(Log.ASSERT, "", "Ciudad entregada por nombre:" + nombre)
// Coger la respuesta del rest API de la consulta de localidad por nombre
var respuesta = quotesApi.get_localidad_nombre(nombre, apikey = api_key)
Log.println(Log.ASSERT, "respuesta", respuesta.toString())
// Convertir la respuesta al objeto: List<Localidad>
var ciudades = respuesta.body()
key = ciudades?.get(0)?.Key.toString()
ciudad_texto = ciudades?.get(0)?.EnglishName.toString()
Log.println(Log.ASSERT, "", key)
Log.println(Log.ASSERT, "", ciudad_texto)
}
else {
if (p_key == "") {
// Coger la respuesta del rest API de la consulta de localidad por geoposición (longitud y latitud)
var respuesta = quotesApi.get_localidad_geoposition(
q = longitud.toString() + "," + latitud.toString(),
apikey = api_key
)
// Convertir la respuesta al objeto: Localidad
var ciudad = respuesta.body()
key = ciudad?.Key.toString()
ciudad_texto = ciudad?.localizedName.toString()
} else {
key = p_key
}
}
// Coger la respuesta del rest API de la consulta de las condiciones actuales
val respuesta_cond_act = quotesApi.get_condiciones_actuales(localidad = key, apikey = api_key, details = true, metric = true)
// Convertir la respuesta al objeto: List<Condiciones>
val cond_act = respuesta_cond_act.body()
// Coger la respuesta del rest API de la consulta de la previción de 1 dia
val respuesta_prev_1day = quotesApi.get_prevision_1_dia(localidad = key, apikey = api_key, details = true, metric = true)
// Convertir la respuesta al objeto: Previccion
val prev_1day = respuesta_prev_1day.body()
// Coger la respuesta del rest API de la consulta de la previcción de 5 dias
val respuesta_prev_5d = quotesApi.get_prevision_5_dias(localidad = key, apikey = api_key, details = true, metric = true)
// Convertir la respuesta al objeto: Previccion_5dias
val prev_5d = respuesta_prev_5d.body()
// Coger la respuesta del rest API de la consulta de la previcción de 12 horas
val respuesta_prev_12h = quotesApi.get_prevision_12_horas(localidad = key, apikey = api_key, details = true, metric = true)
// Convertir la respuesta al objeto: List<Previccion_12Horas>
val prev_12h = respuesta_prev_12h.body()
resultado.ciudad = ciudad_texto
// CARTA PRICIPAL
if (cond_act?.get(0) != null) {
resultado.temperatura_actual = cond_act?.get(0)?.Temperature?.Metric?.Value
resultado.unidades_temperatura = cond_act?.get(0)?.Temperature?.Metric?.UnitType.toString()
resultado.icono = cond_act?.get(0)?.WeatherIcon
resultado.icono_frase = cond_act?.get(0)?.WeatherText
}
if (prev_1day != null) {
resultado.temperatura_maxima = prev_1day?.DailyForecasts?.get(0)?.Temperature?.Maximum?.Value
resultado.temperatura_minima = prev_1day?.DailyForecasts?.get(0)?.Temperature?.Minimum?.Value
}
// DETALLES
if (cond_act?.get(0) != null) {
resultado.presion = cond_act?.get(0)?.Pressure?.Metric?.Value
resultado.uv = cond_act?.get(0)?.UVIndex
resultado.uv_text = cond_act?.get(0)?.UVIndexText
resultado.humedad_relativa = cond_act?.get(0)?.RelativeHumidity
resultado.viento = cond_act?.get(0)?.Wind?.Speed?.Metric?.Value
resultado.direccion_viento = cond_act?.get(0)?.Wind?.Direction?.Localized
}
// 12 HORAS
if (prev_12h?.get(0) != null) {
resultado.hora_1 = prev_12h?.get(0)?.DateTime?.toString().toString()
resultado.temperatura_hora_1 = prev_12h?.get(0)?.Temperature?.Value!!
resultado.icono_hora_1 = prev_12h.get(0).WeatherIcon!!
resultado.hora_2 = prev_12h.get(1).DateTime.toString()
resultado.temperatura_hora_2 = prev_12h.get(1).Temperature?.Value!!
resultado.icono_hora_2 = prev_12h.get(1).WeatherIcon!!
resultado.hora_3 = prev_12h.get(2).DateTime.toString()
resultado.temperatura_hora_3 = prev_12h.get(2).Temperature?.Value!!
resultado.icono_hora_3 = prev_12h.get(2).WeatherIcon!!
resultado.hora_4 = prev_12h?.get(3)?.DateTime.toString()
resultado.temperatura_hora_4 = prev_12h.get(3).Temperature?.Value!!
resultado.icono_hora_4 = prev_12h.get(3).WeatherIcon!!
resultado.hora_5 = prev_12h.get(4).DateTime.toString()
resultado.temperatura_hora_5 = prev_12h?.get(4)?.Temperature?.Value!!
resultado.icono_hora_5 = prev_12h?.get(4)?.WeatherIcon!!
resultado.hora_6 = prev_12h?.get(5)?.DateTime.toString()
resultado.temperatura_hora_6 = prev_12h?.get(5)?.Temperature?.Value!!
resultado.icono_hora_6 = prev_12h?.get(5)?.WeatherIcon!!
resultado.hora_7 = prev_12h?.get(6)?.DateTime.toString()
resultado.temperatura_hora_7 = prev_12h?.get(6)?.Temperature?.Value!!
resultado.icono_hora_7 = prev_12h?.get(6)?.WeatherIcon!!
resultado.hora_8 = prev_12h?.get(7)?.DateTime.toString()
resultado.temperatura_hora_8 = prev_12h?.get(7)?.Temperature?.Value!!
resultado.icono_hora_8 = prev_12h?.get(7)?.WeatherIcon!!
resultado.hora_9 = prev_12h?.get(8)?.DateTime.toString()
resultado.temperatura_hora_9 = prev_12h?.get(8)?.Temperature?.Value!!
resultado.icono_hora_9 = prev_12h?.get(8)?.WeatherIcon!!
resultado.hora_10 = prev_12h?.get(9)?.DateTime.toString()
resultado.temperatura_hora_10 = prev_12h?.get(9)?.Temperature?.Value!!
resultado.icono_hora_10 = prev_12h?.get(9)?.WeatherIcon!!
resultado.hora_11 = prev_12h?.get(10)?.DateTime.toString()
resultado.temperatura_hora_11 = prev_12h?.get(10)?.Temperature?.Value!!
resultado.icono_hora_11 = prev_12h?.get(10)?.WeatherIcon!!
resultado.hora_12 = prev_12h?.get(11)?.DateTime.toString()
resultado.temperatura_hora_12 = prev_12h?.get(11)?.Temperature?.Value!!
resultado.icono_hora_12 = prev_12h?.get(11)?.WeatherIcon!!
}
// 5 dias
if (prev_5d != null) {
resultado.fecha_dia_1 = prev_5d?.DailyForecasts?.get(0)?.Date.toString()
resultado.frase_dia_1 = prev_5d?.DailyForecasts?.get(0)?.Day?.ShortPhrase.toString()
resultado.icono_dia_1 = prev_5d?.DailyForecasts?.get(0)?.Day?.Icon!!
resultado.Temp_max_dia_1 = prev_5d?.DailyForecasts?.get(0)?.Temperature?.Maximum?.Value!!
resultado.Temp_min_dia_1 = prev_5d?.DailyForecasts?.get(0)?.Temperature?.Minimum?.Value!!
resultado.fecha_dia_2 = prev_5d?.DailyForecasts?.get(1)?.Date.toString()
resultado.frase_dia_2 = prev_5d?.DailyForecasts?.get(1)?.Day?.ShortPhrase.toString()
resultado.icono_dia_2 = prev_5d?.DailyForecasts?.get(1)?.Day?.Icon!!
resultado.Temp_max_dia_2 = prev_5d?.DailyForecasts?.get(1)?.Temperature?.Maximum?.Value!!
resultado.Temp_min_dia_2 = prev_5d?.DailyForecasts?.get(1)?.Temperature?.Minimum?.Value!!
resultado.fecha_dia_3 = prev_5d?.DailyForecasts?.get(2)?.Date.toString()
resultado.frase_dia_3 = prev_5d?.DailyForecasts?.get(2)?.Day?.ShortPhrase.toString()
resultado.icono_dia_3 = prev_5d?.DailyForecasts?.get(2)?.Day?.Icon!!
resultado.Temp_max_dia_3 =prev_5d?.DailyForecasts?.get(2)?.Temperature?.Maximum?.Value!!
resultado.Temp_min_dia_3 = prev_5d?.DailyForecasts?.get(2)?.Temperature?.Minimum?.Value!!
resultado.fecha_dia_4 = prev_5d?.DailyForecasts?.get(3)?.Date.toString()
resultado.frase_dia_4 = prev_5d?.DailyForecasts?.get(3)?.Day?.ShortPhrase.toString()
resultado.icono_dia_4 = prev_5d?.DailyForecasts?.get(3)?.Day?.Icon!!
resultado.Temp_max_dia_4 = prev_5d?.DailyForecasts?.get(3)?.Temperature?.Maximum?.Value!!
resultado.Temp_min_dia_4 = prev_5d?.DailyForecasts?.get(3)?.Temperature?.Minimum?.Value!!
resultado.fecha_dia_5 = prev_5d?.DailyForecasts?.get(4)?.Date.toString()
resultado.frase_dia_5 = prev_5d?.DailyForecasts?.get(4)?.Day?.ShortPhrase.toString()
resultado.icono_dia_5 = prev_5d?.DailyForecasts?.get(4)?.Day?.Icon!!
resultado.Temp_max_dia_5 = prev_5d?.DailyForecasts?.get(4)?.Temperature?.Maximum?.Value!!
resultado.Temp_min_dia_5 = prev_5d?.DailyForecasts?.get(4)?.Temperature?.Minimum?.Value!!
}
datos_adquiridos = true
Log.println(Log.ASSERT, "datos_tiempo", resultado.toString())
}
}
}
DataModel
data class Datos_Tiempo #RequiresApi(Build.VERSION_CODES.O) constructor(
// Card principal
var ciudad: String? = "Cordoba",
var temperatura_actual: Double? = 18.0,
var temperatura_maxima: Double? = 12.0,
var temperatura_minima: Double? = 6.0,
var unidades_temperatura: String? = "grados",
var icono: Int? = 1,
var icono_frase: String? = "Cloudy",
// Detalles
var presion: Double? = 1020.0,
var direccion_viento: String? = "Sur",
var viento: Double? = 30.0,
var uv: Int? = 4,
var uv_text: String? = "Low",
var humedad_relativa: Double? = 50.0,
#DrawableRes val icon: Int? = R.drawable.ic_1,
val data: String? = "45",
val units: String? = "km/h",
val color: Color? = GreyCard,
//12horas
var hora_1: String = "2022-12-07T12:00:00+01:00",
var icono_hora_1: Int = 6,
var temperatura_hora_1: Double = 13.5,
var temperatura_hora_2: Double = 12.3,
var hora_2: String = "2022-12-07T13:00:00+01:00",
var icono_hora_2: Int = 12,
var temperatura_hora_3: Double = 14.3,
var hora_3: String = "2022-12-07T14:00:00+01:00",
var icono_hora_3: Int = 13,
var temperatura_hora_4: Double = 15.3,
var hora_4: String = "2022-12-07T15:00:00+01:00",
var icono_hora_4: Int = 15,
var temperatura_hora_5: Double = 13.3,
var hora_5: String = "2022-12-07T16:00:00+01:00",
var icono_hora_5: Int = 13,
var temperatura_hora_6: Double = 12.3,
var hora_6: String = "2022-12-07T17:00:00+01:00",
var icono_hora_6: Int = 12,
var temperatura_hora_7: Double = 12.3,
var hora_7: String = "2022-12-07T18:00:00+01:00",
var icono_hora_7: Int = 6,
var temperatura_hora_8: Double = 13.3,
var hora_8: String = "2022-12-07T19:00:00+01:00",
var icono_hora_8: Int = 7,
var temperatura_hora_9: Double = 11.3,
var hora_9: String = "2022-12-07T20:00:00+01:00",
var icono_hora_9: Int = 6,
var temperatura_hora_10: Double = 14.3,
var hora_10: String = "2022-12-07T21:00:00+01:00",
var icono_hora_10: Int = 6,
var temperatura_hora_11: Double = 13.3,
var hora_11: String = "2022-12-07T22:00:00+01:00",
var icono_hora_11: Int = 26,
var temperatura_hora_12: Double = 12.3,
var hora_12: String = "2022-12-07T23:00:00+01:00",
var icono_hora_12: Int = 36,
//5dias
var fecha_dia_1: String = "2022-12-07T18:00:00+01:00",
var frase_dia_1: String = "Mostly Cloudy w/ T-Storms",
var icono_dia_1: Int = 17,
var Temp_max_dia_1: Double = 12.0,
var Temp_min_dia_1: Double = 2.0,
var fecha_dia_2: String = "2022-12-08T18:00:00+01:00",
var frase_dia_2: String = "Rain",
var icono_dia_2: Int = 18,
var Temp_max_dia_2: Double = 15.0,
var Temp_min_dia_2: Double = 4.0,
var fecha_dia_3: String = "2022-12-09T18:00:00+01:00",
var frase_dia_3: String = "Flurries",
var icono_dia_3: Int = 19,
var Temp_max_dia_3: Double = 16.0,
var Temp_min_dia_3: Double = 5.0,
var fecha_dia_4: String = "2022-12-10T18:00:00+01:00",
var frase_dia_4: String = "Mostly Cloudy w/ Flurries",
var icono_dia_4: Int = 20,
var Temp_max_dia_4: Double = 14.0,
var Temp_min_dia_4: Double = 4.0,
var fecha_dia_5: String = "2022-12-11T18:00:00+01:00",
var frase_dia_5: String = "Mostly Cloudy w/ T-Storms",
var icono_dia_5: Int = 16,
var Temp_max_dia_5: Double = 16.0,
var Temp_min_dia_5: Double = 5.0,
)
Two major problems.
First, you are creating your instance of Accesso_API in the Composable, so it is recreated every time things recompose, so you end up with many copies (probably an infinite loop that will eventually crash the device with out-of-memory error), and you are always looking at a new copy who doesn't have any fetched data yet. You need to wrap it in remember { } so it is initialized only once:
val acceso = remember {
Accesso_API()
.apply { coger_tiempo_nombre("Madrid") }
}
Second, you cannot do this kind of thing in UI code:
while (!acceso.datos_adquiridos) {}
This will freeze the whole device because it blocks the main thread.
Compose is meant to be reactive. Don't wait and repeatedly poll values. Create your data property as State that the Composable uses. When the data isn't ready yet, your composable should show a loading indicator or blank screen or something.
So, in your Accesso_API class, change resultado to be MutableState, and you can use null to represent the state when no data is acquired yet:
var resultado: Datos_Tiempo? by mutableStateOf(null)
And completely delete the datos_adquiridos property and any code where you use it.
In your composable, you can get a reference to this state, and you can determine whether it is received yet by checking if it is null.
val resultado = acceso.resultado
if (resultado == null) {
// show screen with loading indicator
return
}
// the rest of your code that builds the screen using non-null resultado.
There could be other problems to fix, but you have so much code I didn't go through it all in detail.
Side note, this kind of repetitive code should be avoided:
//12horas
var hora_1: String = "2022-12-07T12:00:00+01:00",
var icono_hora_1: Int = 6,
var temperatura_hora_1: Double = 13.5,
var temperatura_hora_2: Double = 12.3,
var hora_2: String = "2022-12-07T13:00:00+01:00",
var icono_hora_2: Int = 12,
//...
Use lists or arrays instead of many similar properties! Then you can iterate things and won't have super long functions with repetitive code wherever you work with this data class.

how to update a list by an other list of the same type on kotlin

I have 2 list of Skill object.
AllSkills represent the full list of skills that can be found in the app.
UserSkills represent the skills that the user has on his account.
What I want to do is to replace any skill in AllSkill that exist in UserSkill (having the same id) by the skill of UserSkill,
But I don't understand how to do it, can someone help me pls ?
Exemple:
val allSkills = listOf<Skill>(Skill(id = 0, note = null), Skill(id = 1, note = null)
val userSkills = listOf<Skill>(Skill(id = 1, note = 2)
then the result I want is :
val result = listOf<Skill>(Skill(id = 0, note=null, Skill(id = 1, note = 2)
-> The skill contained in userSkill (id = 1) as the note of the userSkill
You can transform the user skills into a Map<Int, Skill> by associating them with the ID and proceed with replacing allSkills if it exists in such map.
Haven't tested it but it could look like this:
val allSkills = listOf<Skill>(Skill(id = 0, note = null), Skill(id =0, note = null)
val userSkills = listOf<Skill>(Skill(id = 1, note = 2)
val userSkillsMap = userSkills.associateBy { it.id }
// userSkillsMap[skill.id] returns the skill if it exists
// userSkillsMap[skill.id] returns null if it doesnt exist
// With the ?: (elvis operator) we default back to the present skill
val allSkillsUpdated = allSkills.map { skill -> userSkillsMap[skill.id] ?: skill }
data class Skill(
val id: Int,
val note: Int?
)
val allSkills = listOf(
Skill(id = 0, note = null),
Skill(id = 1, note = null)
)
val userSkills = listOf(
Skill(id = 1, note = 2)
)
val result = allSkills
.map { allSkill ->
userSkills
.firstOrNull { userSkill -> userSkill.id == allSkill.id } ?: allSkill
}
Note that for large skill lists #SomeRandomITboy's solution will most probably be faster.

how use memorycache in this method?

how can i add memorycache in this method ?
this is a section of my code that i want to set memory cache on it.
public IActionResult Index(int pageId = 1, string filter = "",
int startPrice = 0, int endPrice = 0, string getType = "", string orderByType = "date",
List<int> selectedGroups = null, List<int> selectedBrand = null, List<int> selectedTags = null
, List<int> selectedsize = null , string Discount = "")
{
ViewBag.selectedGroups = selectedGroups;
ViewBag.selectedTags = selectedTags;
ViewBag.selectedsize = selectedsize;
ViewBag.Discount = Discount;
ViewBag.getType = getType;
ViewBag.Groups = _productService.GetAllGroup();
ViewBag.Tags = _productService.GetTags().Where(c => c.ActiveRow).ToList();
ViewBag.size = _productService.GetSizes().ToList();
ViewBag.pageId = pageId;
return View(_productService.GetProducttype(pageId, filter, startPrice, endPrice, getType, orderByType, selectedGroups, selectedBrand, 24, selectedTags, selectedsize, Discount));
}
private readonly IMemoryCache _memoryCache;
public Constructor (IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public IActionResult Index(int pageId = 1, string filter = "",
int startPrice = 0, int endPrice = 0, string getType = "", string orderByType = "date",
List<int> selectedGroups = null, List<int> selectedBrand = null, List<int> selectedTags = null
, List<int> selectedsize = null , string Discount = "")
{
ViewBag.selectedGroups = selectedGroups;
ViewBag.selectedTags = selectedTags;
ViewBag.selectedsize = selectedsize;
ViewBag.Discount = Discount;
ViewBag.getType = getType;
var groups = new List<Group>();
if (_memoryCache.TryGetValue("groups", out groups)
{
ViewBag.Groups = groups;
}
else
{
groups = _productService.GetAllGroup();
_memoryCache.Set("groups", groups);
ViewBag.Groups = groups;
}
var tags = new List<Tag>();
if (_memoryCache.TryGetValue("tags", out tags)
{
ViewBag.Tags = tags;
}
else
{
tags = _productService.GetTags().Where(c => c.ActiveRow).ToList();
_memoryCache.Set("tags", tags);
ViewBag.Tags = tags;
}
var sizes = new List<Size>();
if (_memoryCache.TryGetValue("sizes", out sizes)
{
ViewBag.size = sizes;
}
else
{
sizes = _productService.GetSizes().ToList();
_memoryCache.Set("sizes", sizes);
ViewBag.size = sizes;
}
var pageId = null;
if (_memoryCache.TryGetValue("pageId", out pageId))
{
ViewBag.pageId = pageId;
}
else
{
_memoryCache.Set("pageId", pageId);
ViewBag.pageId = pageId;
}
return View(_productService.GetProducttype(pageId, filter, startPrice, endPrice, getType, orderByType, selectedGroups, selectedBrand, 24, selectedTags, selectedsize, Discount));
}

How to pass value for a variable with default value true or false or null in Kotlin

I have written below code in Kotlin for the different values of "isOlListingEnabled" as True, False and null. I got the comment on my PR as "Instead of making new method we can pass value for isOlListingEnabled in method getFlightsOpinionLabModel with default value true or false or null". Can someone please help me to write the below code in such a way that I can handle all three (true, false and null) values in same method.
package com.abc.api.flights.unit.fixture
import com.abc.api.flights.models.domain.TripType
import com.abc.api.flights.models.ui.opinionlab.FlightsOpinionLabModel
import java.util.UUID
object FlightsOpinionLabModelFixture {
fun getFlightsOpinionLabModel(tripType: TripType): FlightsOpinionLabModel = FlightsOpinionLabModel(
siteName = "www.abc.com",
langId = 1033,
duaid = UUID.randomUUID(),
expId = null,
tripType = tripType,
isOlListingEnabled = true
)
fun getFlightsOpinionLabModelWithoutListingEnabled(tripType: TripType): FlightsOpinionLabModel = FlightsOpinionLabModel(
siteName = "www.abc.com",
langId = 1033,
duaid = UUID.randomUUID(),
expId = null,
tripType = tripType,
isOlListingEnabled = false
)
fun getFlightsOpinionLabModelWitListingEnabledNull(tripType: TripType): FlightsOpinionLabModel = FlightsOpinionLabModel(
siteName = "www.abc.com",
langId = 1033,
duaid = UUID.randomUUID(),
expId = null,
tripType = tripType,
isOlListingEnabled = null
)
}
your FlightsOpinionLabModelFixture can be simplified in such way:
object FlightsOpinionLabModelFixture {
fun getFlightsOpinionLabModel(tripType: TripType, isOlListingEnabled: Boolean? = true): FlightsOpinionLabModel = FlightsOpinionLabModel(
siteName = "www.abc.com",
langId = 1033,
duaid = UUID.randomUUID(),
expId = null,
tripType = tripType,
isOlListingEnabled = isOlListingEnabled
)
}
invokation example:
// FlightsOpinionLabModelFixture.getFlightsOpinionLabModelWithoutListingEnabled(type)
FlightsOpinionLabModelFixture.getFlightsOpinionLabModel(type, isOlListingEnabled = false)

ConstructorException parsing XML with Retrofit and SimpleXML (Parameter does not have a match)

*SOLUTION IS IN THE FIRST ANSWER
I'm pretty noob using SimpleXML Converter so models and annotations may be wrong.
This is the XML I receive:
<?xml version="1.0" encoding="UTF-8"?>
<cards-summary-response xmlns="http:/mywebpage.com/rest-api">
<card-summary>
<identifier>51641C1B23931</identifier>
<display-name>Debit Card</display-name>
<program-name>plastic_debit</program-name>
<status>Blocked</status>
</card-summary>
<card-summary>
<identifier>4E1BDFCC1D6</identifier>
<display-name>Virtual Debit</display-name>
<program-name>virtual_debit</program-name>
<status>Active</status>
</card-summary>
</cards-summary-response>
My models:
CardSummaryResponse.kt
#Root(strict = false, name = "cards-summary-response")
data class CardSummaryResponse constructor(
#ElementList(
required = false,
name = "card-summary",
entry = "card-summary",
inline = true,
empty = true
)
var cardsSummaryList: MutableList<CardSummary>? = null
)
CardSummary.kt
#Root(name = "card-summary")
data class CardSummary #JvmOverloads constructor(
#field:Element(name = "identifier", required = true)
var identifier: String = "",
#field:Element(name = "status", required = true)
var status: String = ""
)
API configuration:
retrofit = Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.createNonStrict(
Persister(AnnotationStrategy())
)
)
.baseUrl(CallsConfiguration.BASE_URL_WIRECARD)
.client(clientBuilder.build())
.build()
service = retrofit.create(RetrofitInterface::class.java)
And RetrofitInterface (this class is in Java):
#GET("webservices/wd-test.phtml")
Call<CardSummaryResponse> getCardsSummary();
I'm always getting the same exception:
java.lang.Error: org.simpleframework.xml.core.ConstructorException:
Parameter 'card-summary' does not have a match in class
com.app.account.model.CardSummaryResponse
Any suggestions?
I have managed to make it work using the following models:
CardSummaryResponse.tk
#Root(strict = false, name = "cards-summary-response")
data class CardSummaryResponse constructor(
#field:ElementList(
required = false,
name = "card-summary",
entry = "card-summary",
inline = true,
empty = true
)
var cardsSummaryList: MutableList<CardSummary>? = null
)
CardSummary.tk
#Root(name = "card-summary")
data class CardSummary constructor(
#field:Element(name = "identifier", required = true)
var identifier: String = "",
#field:Element(name = "status", required = true)
var status: String = ""
)
In my case, I was using 'val' in the data class. After spending 3 hours, I found the solution: just replace 'val with 'var' and give the default value.
Here are my data classes that are working fine after the solution:
sealed class Feeds {
#Root(name = "rss", strict = false)
data class RssFeed constructor(#field:Element(name = "channel") var channel: RssChannel? = null) :
Feeds()
#Root(name = "channel", strict = false)
data class RssChannel constructor(
#field:ElementList(
name = "item",
inline = true,
required = false
) var item: List<RssItem>? = null
) : Feeds()
#Root(name = "item", strict = false)
data class RssItem constructor(
#field:Element(name = "title") var title: String = "",
#field:Element(name = "description") var description: String = "",
#field:Element(name = "link") var link: String = ""
) : Feeds()
}
Happy Coding!!!