My app works without errors and updates the field in the firestore
when I hard-coded the value that needs to be updated. However, when I the following code to get the value from the spinner
to update a field in the firestore, the app crashes.
I am using kotlin
and viewBinding
.
Following is the error in the Logcat
--------- beginning of crash 2021-06-07 14:00:12.155 23175-23175/com.trad E/AndroidRuntime: FATAL EXCEPTION: main Process: com.trad, PID: 23175 kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized at com.trad.ui.adapters.OrderStatusListAdapter.access$getBinding$p(OrderStatusListAdapter.kt:32) at com.trad.ui.adapters.OrderStatusListAdapter$onBindViewHolder$1.onClick(OrderStatusListAdapter.kt:84) at android.view.View.performClick(View.java:8160) at android.widget.TextView.performClick(TextView.java:16222) at android.view.View.performClickInternal(View.java:8137) at android.view.View.access$3700(View.java:888) at android.view.View$PerformClick.run(View.java:30236) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8512) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
2021-06-07 14:00:12.234 23175-23175/com.trad I/Process: Sending signal. PID: 23175 SIG: 9
Following is the OrderStatusListAdapter.kt
class
The error that is pointing at line number 32 and 84 are mentioned as a comment in the code.
open class OrderStatusListAdapter( //LINE # 32 MENTIONED IN THE ERROR
private val context: Context,
private var list: ArrayList<OrderStatus>,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
lateinit var newOrderStatus: Spinner
private lateinit var binding: OrderStatusLayoutBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
LayoutInflater.from(context).inflate(
R.layout.order_status_layout,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = list[position]
if (holder is MyViewHolder) {
GlideLoader(context).loadProductPicture(
model.image,
holder.itemView.iv_order_status_item_image
)
val dateFormat = "dd MMM yyyy HH:mm"
val formatter = SimpleDateFormat(dateFormat, Locale.getDefault())
val calendar: Calendar = Calendar.getInstance()
calendar.timeInMillis = model.order_datetime
val orderDateTime = formatter.format(calendar.time)
holder.itemView.tv_order_status_order_date.text = orderDateTime
holder.itemView.tv_order_status_item_name.text = model.items[0].title
holder.itemView.tv_order_status_item_price.text = "$${model.total_amount}"
model.order_datetime.toString()
holder.itemView.tv_order_status.text = model.order_status
holder.itemView.tv_order_status_order_id.text = model.id
holder.itemView.btn_order_status_change_status.setOnClickListener {
binding.spnOrderChangeStatus.onItemSelectedListener = // LINE 84 MENTIONED IN THE ERROR
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
Toast.makeText(
context,
"Selected value is ${
parent?.getItemAtPosition(position).toString()
}",
Toast.LENGTH_SHORT
).show()
val newstat = parent?.getItemAtPosition(position).toString()
FirestoreClass().updateOrderStatus(model.id, newstat)
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
}
holder.itemView.ib_order_status_delete_product.visibility = View.GONE
holder.itemView.setOnClickListener {
val intent = Intent(context, SoldProductDetailsActivity::class.java)
intent.putExtra(Constants.EXTRA_SOLD_PRODUCT_DETAILS, model)
context.startActivity(intent)
}
}
}
override fun getItemCount(): Int {
return list.size
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
Means that you tried to use the binding
property before it being initialized.
binding
should be declared in the place where you define the layout; and this is typically in onCreateViewHolder()
callback at which you defined the default inflater without using data binding, to fix that:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
// initialize the binding either use:
binding = DataBindingUtil.inflate(inflater, R.layout.order_status_layout, parent, false)
// or use:
// binding = OrderStatusLayoutBinding.inflate(inflater)
return MyViewHolder(binding)
}
The second issue: you accept a View
as constructor parameter in MyViewHolder
while it should accept the item binding type which is OrderStatusLayoutBinding
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
To fix that:
class MyViewHolder(binding: OrderStatusLayoutBinding) : RecyclerView.ViewHolder(binding.root)
UPDATE
I got the
error Unresolved reference: DataBindingUtil alsoDataBindingUtil and inflater in binding = DataBindingUtil.inflate(inflater, R.layout.order_status_layout, parent, false) are red.
You need to enable dataBinding in build.gradle (Module level) and this requires to have kotlin-kapt
plugin:
plugins {
…
id 'kotlin-kapt'
}
android {
…
buildFeatures {
dataBinding true
}
}