in my agent_details_activity.xml:
<ImageView
android:id="@+id/imageViewPhoto"
android:layout_width="0dp"
android:layout_height="400dp"
app:agentImageUrl="@{item.url}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolBarContainer" />
in activity:
class AgentDetailsActivity : AppCompatActivity() {
private lateinit var binding: AgentDetailsActivityBinding
companion object {
val AGENT_DETAILS = AgentDetailsActivity::class.java.name + "_AGENT_DETAILS"
}
private val TAG = AgentDetailsActivity::class.java.name
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = AgentDetailsActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.setHandler(this);
}
@BindingAdapter("agentImageUrl")
fun loadImage(view: ImageView, imageUrl: String) {
Glide.with(view.context)
.load(imageUrl)
.apply(RequestOptions().error(R.drawable.no_image))
.into(view)
}
but in runtime I get error:
Shutting down VM
FATAL EXCEPTION: main
Process: com.android.testproject.android.kotlin.debug, PID: 24924
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.testproject.android.kotlin.debug/com.android.testproject.android.kotlin.coroutine_retrofit.ui.activity.AgentDetailsActivity}: java.lang.IllegalStateException: Required DataBindingComponent is null in class AgentDetailsActivityBindingImpl. A BindingAdapter in com.android.testproject.android.kotlin.coroutine_retrofit.ui.activity.AgentDetailsActivity is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Required DataBindingComponent is null in class AgentDetailsActivityBindingImpl. A BindingAdapter in com.android.testproject.android.kotlin.coroutine_retrofit.ui.activity.AgentDetailsActivity is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
at androidx.databinding.ViewDataBinding.ensureBindingComponentIsNotNull(ViewDataBinding.java:666)
at com.android.testproject.android.kotlin.databinding.AgentDetailsActivityBindingImpl.<init>(AgentDetailsActivityBindingImpl.java:40)
at com.android.testproject.android.kotlin.databinding.AgentDetailsActivityBindingImpl.<init>(AgentDetailsActivityBindingImpl.java:32)
at com.android.testproject.android.kotlin.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:52)
at androidx.databinding.MergedDataBinderMapper.getDataBinder(MergedDataBinderMapper.java:74)
at androidx.databinding.DataBindingUtil.bind(DataBindingUtil.java:199)
at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:130)
at androidx.databinding.ViewDataBinding.inflateInternal(ViewDataBinding.java:1366)
at com.android.testproject.android.kotlin.databinding.AgentDetailsActivityBinding.inflate(AgentDetailsActivityBinding.java:95)
at com.android.testproject.android.kotlin.databinding.AgentDetailsActivityBinding.inflate(AgentDetailsActivityBinding.java:81)
at com.android.testproject.android.kotlin.coroutine_retrofit.ui.activity.AgentDetailsActivity.onCreate(AgentDetailsActivity.kt:37)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
In my case I found a really simple method, I had the same error as you. I just had to add @JvmStatic
annotation.
The code will look something like this:
companion object {
@JvmStatic // add this line !!
@BindingAdapter("agentImageUrl")
fun loadImage(view: ImageView, imageUrl: String) {
Glide.with(view.context)
.load(imageUrl)
.apply(RequestOptions().error(R.drawable.no_image))
.into(view)
}
}
To elaborate on @mahdi shahbazi answer (The bind adapter method must be static):
In kotlin, place your binding method outside of any class (so in your case oustide of the Activity class). This will do the trick. In your case, it will look like:
@BindingAdapter("agentImageUrl")
fun loadImage(view: ImageView, imageUrl: String) {
Glide.with(view.context)
.load(imageUrl)
.apply(RequestOptions().error(R.drawable.no_image))
.into(view)
}
class AgentDetailsActivity : AppCompatActivity() {
private lateinit var binding: AgentDetailsActivityBinding
companion object {
val AGENT_DETAILS = AgentDetailsActivity::class.java.name + "_AGENT_DETAILS"
}
private val TAG = AgentDetailsActivity::class.java.name
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = AgentDetailsActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.setHandler(this);
}
...
}
I have been able to come up with this answer thanks to this article: https://proandroiddev.com/custom-attributes-using-bindingadapters-in-kotlin-971ef8fcc259. There are lots of other good tips in it, I recommend looking into it for yummies about view binding.
Yes, first of all place your binding method outside of any class. Second, make imageUrl nullable! Becouse if you will have imageUrl is null you will have crash instead of onError is invoked
@BindingAdapter("agentImageUrl")
fun loadImage(view: ImageView, imageUrl: String?) {
Glide.with(view.context)
.load(imageUrl)
.apply(RequestOptions().error(R.drawable.no_image))
.into(view)
}
// Solution 1
@BindingAdapter("android:loadImage")
fun loadImage(userImageView: ImageView, imageUrl: String): Unit {
Glide
.with(userImageView)
.load(imageUrl)
.into(userImageView)
}
**This is my solution, I have written my function outside the class**
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With