I am following the kotlin basics training camp provided by google. Currently learning shared viewmodel to build the cupcake app. I have coded exactly same as them but I am facing the below given error. For reference here is the github repository.
I don't know why the android studio is giving me the error. From my point of view, it is completely right. Please help me if you know how to solve this or what mistake I have done.
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout for selecting a flavor -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".FlavorFragment">
<data>
<variable
name="viewModel"
type="com.example.cupcake.model.OrderViewModel" />
<variable
name="flavorFragment"
type="com.example.cupcake.FlavorFragment" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/side_margin">
<RadioGroup
android:id="@+id/flavor_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:id="@+id/vanilla"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.flavor.equals(@string/vanilla)}"
android:onClick="@{() -> viewModel.setFlavor(@string/vanilla)}"
android:text="@string/vanilla" />
<RadioButton
android:id="@+id/chocolate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.flavor.equals(@string/chocolate)}"
android:onClick="@{() -> viewModel.setFlavor(@string/chocolate)}"
android:text="@string/chocolate" />
<RadioButton
android:id="@+id/red_velvet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.flavor.equals(@string/red_velvet)}"
android:onClick="@{() -> viewModel.setFlavor(@string/red_velvet)}"
android:text="@string/red_velvet" />
<RadioButton
android:id="@+id/salted_caramel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.flavor.equals(@string/salted_caramel)}"
android:onClick="@{() -> viewModel.setFlavor(@string/salted_caramel)}"
android:text="@string/salted_caramel" />
<RadioButton
android:id="@+id/coffee"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.flavor.equals(@string/coffee)}"
android:onClick="@{() -> viewModel.setFlavor(@string/coffee)}"
android:text="@string/coffee" />
</RadioGroup>
<View
android:id="@+id/divider"
style="@style/Widget.Cupcake.Divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="@dimen/side_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/flavor_options" />
<TextView
android:id="@+id/subtotal"
style="@style/Widget.Cupcake.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/side_margin"
android:text="@{@string/subtotal_price(viewModel.price)}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider"
tools:text="Subtotal $5.00" />
<Button
android:id="@+id/cancel_button"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/side_margin"
android:onClick="@{() -> flavorFragment.cancelOrder()}"
android:text="@string/cancel"
app:layout_constraintEnd_toStartOf="@id/next_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/next_button" />
<Button
android:id="@+id/next_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/side_margin"
android:onClick="@{() -> flavorFragment.goToNextScreen()}"
android:text="@string/next"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cancel_button"
app:layout_constraintTop_toBottomOf="@id/subtotal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>
I am facing an error at the line of every android:checked radio button. Below is the error
@{viewModel.date.equals(viewModel.dateOptions[2])' is incompatible with attribute checked (attr) boolean.
ViewModel Code:-
package com.example.cupcake.model
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel
import java.text.NumberFormat
import java.text.SimpleDateFormat
import java.util.*
private const val PRICE_PER_CUPCAKE = 2.00
private const val PRICE_FOR_SAME_DAY_PICKUP = 3.00
class OrderViewModel : ViewModel() {
init {
resetOrder()
}
private val _quantity = MutableLiveData<Int>()
val quantity: LiveData<Int> = _quantity
private val _flavor = MutableLiveData<String>()
val flavor: LiveData<String> = _flavor
private val _date = MutableLiveData<String>()
val date: LiveData<String> = _date
private val _price = MutableLiveData<Double>()
val price: LiveData<String> = Transformations.map(_price) {
NumberFormat.getCurrencyInstance().format(it)
}
val dateOptions = getPickupOptions()
fun setQuantity(numberCupcakes: Int) {
_quantity.value = numberCupcakes
updatePrice()
}
fun setDate(pickupDate: String) {
_date.value = pickupDate
updatePrice()
}
fun setFlavor(desiredFlavor: String) {
_flavor.value = desiredFlavor
}
fun hasNoFlavorSet(): Boolean {
return _flavor.value.isNullOrEmpty()
}
private fun getPickupOptions(): List<String> {
val options = mutableListOf<String>()
val formatter = SimpleDateFormat("EE MMM d", Locale.getDefault())
val calendar = Calendar.getInstance()
// Create a list of dates starting with the current date and the following 3 dates
repeat(4) {
options.add(formatter.format(calendar.time))
calendar.add(Calendar.DATE, 1)
}
return options
}
private fun updatePrice() {
var calculatedPrice = (quantity.value ?: 0) * PRICE_PER_CUPCAKE
// If the user selected the first option (today) for pickup, add the surcharge
if (dateOptions[0] == _date.value) {
calculatedPrice += PRICE_FOR_SAME_DAY_PICKUP
}
_price.value = calculatedPrice
}
fun resetOrder() {
_quantity.value = 0
_flavor.value = ""
_date.value = dateOptions[0]
_price.value = 0.0
}
}
Fragment Pick_up code:-
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout for selecting a pickup date -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".PickupFragment">
<data>
<variable
name="viewModel"
type="com.example.cupcake.model.OrderViewModel" />
<variable
name="pickupFragment"
type="com.example.cupcake.PickupFragment" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/side_margin">
<RadioGroup
android:id="@+id/date_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:id="@+id/option0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.date.equals(viewModel.dateOptions[0])"
android:onClick="@{() -> viewModel.setDate(viewModel.dateOptions[0])}"
android:text="@{viewModel.dateOptions[0]}"
tools:text="Thursday" />
<RadioButton
android:id="@+id/option1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked= "@{viewModel.date.equals(viewModel.dateOptions[1])}"
android:onClick="@{() -> viewModel.setDate(viewModel.dateOptions[1])}"
android:text="@{viewModel.dateOptions[1]}"
tools:text="Friday" />
<RadioButton
android:id="@+id/option2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.date.equals(viewModel.dateOptions[2])"
android:onClick="@{() -> viewModel.setDate(viewModel.dateOptions[2])}"
android:text="@{viewModel.dateOptions[2]}"
tools:text="Saturday" />
<RadioButton
android:id="@+id/option3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@{viewModel.date.equals(viewModel.dateOptions[3])"
android:onClick="@{() -> viewModel.setDate(viewModel.dateOptions[3])}"
android:text="@{viewModel.dateOptions[3]}"
tools:text="Sunday" />
</RadioGroup>
<View
android:id="@+id/divider"
style="@style/Widget.Cupcake.Divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="@dimen/side_margin"
android:layout_marginBottom="@dimen/side_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/date_options" />
<TextView
android:id="@+id/subtotal"
style="@style/Widget.Cupcake.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/side_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider"
android:text="@{@string/subtotal_price(viewModel.price)"
tools:text="Subtotal $5.00" />
<Button
android:id="@+id/next_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/side_margin"
android:text="@string/next"
android:onClick="@{() -> pickupFragment.goToNextScreen()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subtotal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>