Bindable must be on a member in an Observable class - android

I'm new in data binding , this is my code but I get this error on building
class DatabindingViewModel :ViewModel() {
val currentFruitName:LiveData<String>
get() = FakeRepository.currentName
fun changeNameOnClick()=FakeRepository.changeRandomFoodName()
//two way LiveData
#Bindable
val editTextContext= MutableLiveData<String>()
private val _displayEditTexfContent=MutableLiveData<String>()
val displayEditTexfContent:LiveData<String>
get()=_displayEditTexfContent
fun onDisplayEtText(){
_displayEditTexfContent.value=editTextContext.value
}
this is my xml layout code :
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="binding"
type="ir.persiandesigners.myapplication.databinding.viewmodel.DatabindingViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="50dp"
android:layout_marginRight="50dp"
android:text="#{binding.currentFruitName}"
android:textAppearance="#style/TextAppearance.AppCompat.Display1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:onClick="#{()->binding.changeNameOnClick()}"
android:text="Get Random Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="60dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:ems="10"
android:inputType="textPersonName"
android:text="#={binding.editTextContext}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:onClick="#{()->binding.onDisplayEtText()}"
android:text="Change Display Text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
this is the code I've in the activity:
val viweModel= ViewModelProviders.of(this)
.get(DatabindingViewModel::class.java)
DataBindingUtil.setContentView<ActvitiyDatadindingBinding>(
this,R.layout.actvitiy_datadinding)
.apply {
this.setLifecycleOwner( this#DataBindingAct)
this.binding=viweModel
}
viweModel.editTextContext.observe(this, Observer{
Toast.makeText(this#DataBindingAct,it ,Toast.LENGTH_LONG).show()
})
when I want to build the project and run it , I get this error :
e: error: Bindable must be on a member in an Observable class. DatabindingViewModel is not Observable
could you help me ?
I've tried to clean the project , rebuild and so on but there is an error in my code that I couldn't find
could you help me ?

Just remove #Bindable annotation from Viewmodel and your code will run successfully and error will be resolved.
The #Bindable annotation should only be be applied when you are accessing getter method while extending BaseObservable class which itself implements Observable interface for observing data.
Here LiveData itself is an observable data holder class
So, you don't need to implement #Bindable and BaseObservable class for observing data.
docs: https://developer.android.com/reference/android/databinding/Bindable
I hope things are clear now..

You have to implement Observable Interface and add its methods
here is mine,
class MainViewModel: ViewModel(), Observable {
private val callbacks: PropertyChangeRegistry by lazy { PropertyChangeRegistry()}
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
callbacks.add(callback)
}
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
callbacks.remove(callback)
}
}// class ends here

Do the following step-by-step:
Clean Project
Rebuild Project
Invalidate Caches / Restart
Trust me, it should work. I know the solution is simple but I also wasted my 3 hours 'cuz of this. Follow these 3 steps and you should be good to go.

Related

getting an error when using toDouble() and toIntOrNull()

I'm writing a simple tip calculator app in android studio ( which is one of the programs in the https://developer.android.com/courses/android-basics-kotlin/course course ).
But I'm getting an unexpected error, unresolved reference: toDouble, when I try to covert a string to a double. Even after pasting the solution code from the website into my application, the error won't go away. I also tried first converting the string to an int using toInt function but I get the same error.
Here is the code inside MainActivity.kt.
package com.example.tiptime
import java.text.NumberFormat
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.tiptime.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.calculateButton.setOnClickListener{ calculateTip() }
}
fun calculateTip() {
val stringInTextField = binding.costOfService.text.toString()
val cost = stringInTextField.toDouble()
}
}
Here is my code in activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity"
tools:ignore="UseSwitchCompatOrMaterialXml">
<EditText
android:id="#+id/cost_of_service"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:hint="#string/cost_of_service"
android:inputType="numberDecimal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:autofillHints="#string/cost_of_service" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/how_was_the_service"
android:id="#+id/service_question"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/cost_of_service"/>
<RadioGroup
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/tip_options"
android:checkedButton="#+id/option_twenty_percent"
app:layout_constraintTop_toBottomOf="#id/service_question"
app:layout_constraintStart_toStartOf="parent">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option_twenty_percent"
android:text="#string/amazing_20"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option_eighteen_percent"
android:text="#string/great_18"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option_fifteen_percent"
android:text="#string/ok_15"/>
</RadioGroup>
<Switch
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/round_up_switch"
android:text="#string/round_up_tip"
android:checked="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tip_options" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/calculate"
android:id="#+id/calculate_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/round_up_switch"
/>
<TextView
android:id="#+id/tip_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tip_amount"
app:layout_constraintTop_toBottomOf="#id/calculate_button"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And here is the screenshot of the error
Any help is appreciated!!
Seems like you do not have the latest kotlin support .
Update the Kotlin version to the latest one from :
File ->> Setting -->> Language & Frameworks -->> Kotlin ...
Try after removing
import java.text.NumberFormat
comment
fun calculateTip() {
val stringInTextField = binding.costOfService.text.toString()
val cost = stringInTextField.toDouble()
}
build & clean
uncomment the code in above method you will get correct import
Use
val cost = Double.parseDouble(stringInTextField)

editableText is not working in android studio

I want to take Input from user(their name) with editableText just like the below video(watch at 8:24). But, I am not able to take input because android studio is not recognizing "editableText". Am i missing something?
Android Development Tutorial Video at 8:24
Error ->>
Unresolved reference: nameInput [In the below MainActivity.kt]
MainActivity.kt
package com.example.firstapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun createBirthdayCard(view: View){
val name = nameInput.**editableText**.toString() <-- [error is in this line]
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="140dp"
android:text="Enter Name"
android:textColor="#000000"
android:textSize="50sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:textAlignment="center" />
<EditText
android:id="#+id/nameInput"
android:layout_width="280dp"
android:layout_height="54dp"
android:layout_marginTop="64dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView3"
tools:textAlignment="center" />
<Button
android:id="#+id/createBirthdayCard"
android:layout_width="307dp"
android:layout_height="81dp"
android:layout_marginTop="144dp"
android:maxLines="1"
android:text="Create Birthday Card"
android:textSize="19sp"
android:onClick="createBirthdayCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/nameInput"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
:) :) Thanks for spending your valuable time to help me :) :)
Android kotlin extensions removed at Android studio 4.1V.
I recommend use the ViewBinding or DataBinding.
This is a good reference.
https://android-developers.googleblog.com/2020/11/the-future-of-kotlin-android-extensions.html
ViewBinding : https://developer.android.com/topic/libraries/view-binding?hl=ko
DataBinding : https://developer.android.com/topic/libraries/data-binding
As Android kotlin extensions is deprecated and removed you may use
View binding, Data binding as suggested by Seungho Kang
OR you can declare variable as shown below.
fun createBirthdayCard(view: View){
val editText=findViewById<EditText>(R.id.nameInput)
val name = editText.editableText.toString()
}

Validation using binding adapter

i need some clearance in my concept of understanding the binding adapter implementation.
I am designing a login form with two input fields and a button. I'm trying to use binding adapter to validate those fields using text watcher (which is working fine).
But i'm lost that how can i validate those fields on click of the button.
i'm trying to achieve a clean architecture and remove all kind of dependency between view and ViewModel.
login_activity.xml
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="authModel"
type="com.jpm.ui.auth.AuthViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorSurface"
tools:context=".ui.auth.LoginActivty">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/logo"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginTop="60dp"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/jpm_logo" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/layoutLoginId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="40dp"
android:hint="#string/login_id_hint"
app:layout_constraintTop_toBottomOf="#id/logo"
app:startIconDrawable="#drawable/ic_user"
nullCheck="#{#string/nullError}">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/inputLoginId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={authModel.inputLoginId}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/layoutPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="40dp"
android:hint="#string/password"
app:layout_constraintTop_toBottomOf="#id/layoutLoginId"
app:passwordToggleEnabled="true"
app:startIconDrawable="#drawable/ic_locked">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/inputPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={authModel.inputPassword}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="#+id/btnSignIn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginTop="30dp"
android:background="#drawable/bg_primary_rounded"
android:onClick="#{authModel::authClickListener}"
android:paddingStart="40dp"
android:paddingEnd="40dp"
android:text="#string/sign_in"
android:textColor="#color/textSecondary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/layoutPassword" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/labelCreateAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="#string/don_t_have_an_account"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/txtCreateAccount"
app:layout_constraintTop_toBottomOf="#id/btnSignIn" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/txtCreateAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="20dp"
android:onClick="#{authModel::authClickListener}"
android:text="#string/create_account"
android:textColor="#color/colorPrimary"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toRightOf="#id/labelCreateAccount"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/btnSignIn" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/txtSkip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="#{authModel::authClickListener}"
android:text="#string/skip"
android:textColor="#color/textGrey"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/txtCreateAccount" />
</androidx.constraintlayout.widget.ConstraintLayout>
ValidationUtils.class
import android.util.Log
import androidx.core.widget.doAfterTextChanged
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.databinding.BindingAdapter
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.common.base.Predicates
import com.jpm.R
object ValidationUtils : BaseObservable() {
const val TAG = "VALIDATION"
#BindingAdapter("nullCheck")
#JvmStatic
fun setError(inputLayout: TextInputLayout, errorMsg: String) {
inputLayout.editText?.doAfterTextChanged {
if (it.isNullOrEmpty()) {
inputLayout.isErrorEnabled = true
inputLayout.error = errorMsg
} else {
inputLayout.isErrorEnabled = false
inputLayout.error = null
}
}
}
}
Please help with some suggestion or what can i implement to achieve the validation on button click.
**PS - On Validation on button click setError should be applied on EditText as well **
This is what I'd use in your case:
When your ViewModel's authClickListener() is called, you check/validate every input that is bound with two-way databinding, in your case inputLoginId and the password.
Additionally you set up two error observables, with the type String?, tie does to the error of the respective TextInputLayout and just modify the error messages according to your validation logic

e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors

I have enabled databinding, but while I execute the code I get this error.
error
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
I created a fragment class and XML for that class.
Im able to import datbindingutil class.
I have done rebuilt/ sync with gradle files/ invalidate cache and restart, nothing worked.
xml
<layout>
<!--suppress AndroidUnknownAttribute -->
<data class=".databinding.ProfileFragmentBinding">
<variable
name="user"
type="com.sample.sample.user.User" />
<variable
name="vm"
type="com.sample.sample.user.UserViewModel" />
<variable
name="handler"
type="com.sample.sample.user.profile.ProfileFragment" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profileIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/medium"
android:layout_marginTop="#dimen/medium"
android:contentDescription="#null"
android:src="#mipmap/ic_launcher_round"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:url="#{user.avatarUrl}" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="#+id/profileIV"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#+id/profileIV">
<TextView
android:id="#+id/profileNameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/myriad_pro_semibold"
android:text="#{user.name}"
android:textColor="#color/black_transparent_de"
android:textSize="#dimen/text_regular"
tools:text="NAME" />
<TextView
android:id="#+id/badgeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:fontFamily="#font/myriad_pro_semibold"
android:text="#{user.badge}"
android:textColor="#color/grey_000000"
android:textSize="#dimen/text_regular"
tools:text="Superman" />
<TextView
android:id="#+id/profile_Label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:fontFamily="#font/roboto_bold"
android:text="#{user.badge}"
android:textColor="#color/green_39b54a"
android:textSize="#dimen/text_small"
tools:text="farmer_v1" />
</LinearLayout>
<ImageView
android:id="#+id/badgeIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="#dimen/medium"
android:layout_marginTop="#dimen/medium"
android:contentDescription="#null"
android:src="#mipmap/ic_launcher"
app:error="#{#drawable/ic_profile_default_grey_24dp}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:placeholder="#{#drawable/ic_profile_default_grey_24dp}"
app:url="#{user.badgeUrl}" />
<ImageView
android:id="#+id/locationPinIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium"
android:contentDescription="#null"
android:src="#drawable/ic_location_pin"
app:layout_constraintStart_toStartOf="#+id/profileIV"
app:layout_constraintTop_toBottomOf="#+id/profileIV" />
<TextView
android:id="#+id/profileAddressTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/narrow"
android:fontFamily="#font/roboto"
android:textColor="#color/grey_000000"
app:layout_constraintBottom_toBottomOf="#+id/locationPinIV"
app:layout_constraintLeft_toRightOf="#+id/locationPinIV"
app:layout_constraintTop_toTopOf="#+id/locationPinIV"
tools:text="bangalore, Karnataka" />
<ImageView
android:id="#+id/dobIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/standard"
android:layout_marginTop="#dimen/medium"
android:contentDescription="#null"
android:src="#drawable/ic_dob"
app:layout_constraintLeft_toRightOf="#+id/profileAddressTV"
app:layout_constraintTop_toBottomOf="#+id/profileIV" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/narrow"
android:fontFamily="#font/roboto"
android:textColor="#color/grey_000000"
app:layout_constraintBottom_toBottomOf="#+id/locationPinIV"
app:layout_constraintLeft_toRightOf="#+id/dobIV"
app:layout_constraintTop_toTopOf="#+id/locationPinIV"
tools:text="born on 01/01/2000" />
<TextView
android:id="#+id/activityLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/big"
android:fontFamily="#font/myriad_pro_semibold"
android:text="#string/activities"
android:textColor="#color/black_transparent_de"
android:textSize="#dimen/text_regular"
app:layout_constraintStart_toStartOf="#+id/profileIV"
app:layout_constraintTop_toBottomOf="#+id/locationPinIV" />
<View
android:id="#+id/dividerV"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginEnd="#dimen/small"
android:layout_marginStart="#dimen/small"
android:layout_marginTop="#dimen/regular"
android:background="#color/grey_000000"
app:layout_constraintTop_toBottomOf="#+id/activityLabel" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/dividerV">
<!--<com.google.android.material.tabs.TabLayout
android:id="#+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:pager="#{(pager)}"
app:tabGravity="fill"
app:tabIndicatorColor="#color/black"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/black"
app:tabTextAppearance="#style/CustomTextTab"
app:tabTextColor="#b4ffffff" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tablayout"
app:handler="#{handler}"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />-->
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
class
class ProfileFragment : Fragment() {
#Inject
lateinit var mFactory: ViewModelProvider.Factory
private lateinit var mBinding: ProfileFragmentBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_profile, container, false);
return mBinding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val vm: UserViewModel = getViewModel(mFactory)
mBinding.vm = vm
//mBinding.handler = this
//mBinding.setLifecycleOwner(this)
}
/*#BindingAdapter("bind:handler")
fun bindViewPagerAdapter(view: ViewPager, activity: MainActivity) {
val adapter = ProfilePagerAdapter(view.context, activity.supportFragmentManager)
view.adapter = adapter
}
#BindingAdapter("bind:pager")
fun bindViewPagerTabs(view: TabLayout, pagerView: ViewPager) {
view.setupWithViewPager(pagerView, true)
}*/
}
in my case I was able to find it when the mouse was hovering that line in the build output, as shown here:
without hover:
with hover:
it's really a shame how they show the error, for the simplest error ever, I was trying 10 different solutions as well invalidating the cache and ...
UPDATE:
you can also click here :
and you'll get something like this:
which is very detailed information about the error, I was missing this button in 7 years of Android Development :D
Run ./gradlew build --stacktrace to check the details, which will tell you where the issue happens, something like:
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
Could not find accessor xx
file:xxx/app/src/main/res/layout/fragment_xxxx.xml Line:108
Sometimes if you changed the property name, especially when changed by refactor => rename, the property name won't be changed in xml automatically.
Mostly this error occurs when the name of the variable passed in the XML file through data binding is incorrect. Just hover over the mouse on the error and you would be able to identify the culprit variable there.
if it happen when change jdk versions, delete all build folders in every module that you have on the project,
It's fixed my issue.
delete caches folder to
finder -> home -> click on "command +shift + ." to see hidden folders -> .gradle -> caches

Android-kotlin-binding doesn't update the properties [duplicate]

This question already has an answer here:
Kotlin android. binding not update data
(1 answer)
Closed 5 years ago.
My problem is the binding is work, but not correctly! When I type new text in textfield and then try to get data from this textfield with help binding, I see old data. I tried to find the mistake, but I couldn't.
My activity_fblogin.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<data>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey_main"
android:descendantFocusability="beforeDescendants"
android:fitsSystemWindows="true"
android:focusableInTouchMode="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context="com.example.darkt.makeyouself.activities.FBLogin"
tools:ignore="MissingConstraints">
<EditText
android:id="#+id/userName"
android:layout_width="220dp"
android:layout_height="43dp"
android:ems="10"
android:inputType="textPersonName"
android:text="test01"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Login"/>
<EditText
android:id="#+id/userPass"
android:layout_width="220dp"
android:layout_height="45dp"
android:layout_marginTop="25dp"
android:ems="10"
android:inputType="textPassword"
android:text="123456"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/userName"
tools:layout_editor_absoluteX="74dp"
tools:layout_editor_absoluteY="245dp"
tools:text="Password"/>
<Button
android:id="#+id/loginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Login"
android:textColor="#color/green_main"
app:layout_constraintEnd_toEndOf="#+id/userPass"
app:layout_constraintTop_toBottomOf="#+id/userPass" />
</android.support.constraint.ConstraintLayout>
</layout>
It is my kotlin class for fblogin_activity. I was trying to fixed this problem, but ... Give me idea please!
package com.example.darkt.makeyouself.activities
class FBLogin : AppCompatActivity() {
private var binding: ActivityFbloginBinding? = null
private var auth: FirebaseAuth? = null
private var dbHelper: FirebaseHelper? =null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_fblogin)
auth = FirebaseAuth.getInstance()
dbHelper = FirebaseHelper()
setContentView(R.layout.activity_fblogin)
binding?.executePendingBindings()
signIn.setOnClickListener{_ -> showSignInActivity()}
}
private fun loginToSystem() {
val email = binding?.userName?.text.toString().trim()
val password = binding?.userPass?.text.toString()
binding?.executePendingBindings()
Toast.makeText(this, email, Toast.LENGTH_SHORT).show()
Toast.makeText(this, password, Toast.LENGTH_SHORT).show()
}
}
Example mistake
There is nothing in your layout xml that actually uses databinding.
first in your tag, you will need to define an object to reference for data binding. for example:
<data>
<variable name="user" type="com.myapp.User"/>
</data>
further down in the username/password field you would need to reference this user for the text field
<EditText
android:id="#+id/userName"
android:layout_width="220dp"
android:layout_height="43dp"
android:ems="10"
android:inputType="textPersonName"
android:text="#={user.username}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<EditText
android:id="#+id/userPass"
android:layout_width="220dp"
android:layout_height="45dp"
android:layout_marginTop="25dp"
android:ems="10"
android:inputType="textPassword"
android:text="#={user.password}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/userName"
tools:layout_editor_absoluteX="74dp"
tools:layout_editor_absoluteY="245dp"/>
Note the #={user.username} in the text field. For every property of the class user, you will need to specify a setter/getter. the #= means, update the underlying object when this value changes.
before your "executePendingBindings" you will need to do something like this:
val user = User()
binding.setVariable(BR.user, user)
binding.executePendingBindings()
then you should be good to go.

Categories

Resources