kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized - android

my application is giving the below error that you mentioned above and it says there is an error on line 69, but you have tried all the solutions and could not fix it. You are new to programming and trying to learn, so you are asking for help from experienced people like us.
Can you please help me?
Error Message:
AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.kotlincountries, PID: 15240
kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
at com.example.kotlincountries.adapter.CountryAdapter.onCountryClicked(CountryAdapter.kt:69)
at com.example.kotlincountries.databinding.ItemCountryBindingImpl$OnClickListenerImpl.onClick(ItemCountryBindingImpl.java:173)
at android.view.View.performClick(View.java:7506)
at android.view.View.performClickInternal(View.java:7483)
at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
at android.view.View$PerformClick.run(View.java:29334)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
I have enabled two options in my gradle file.
buildFeatures {
viewBinding = true
dataBinding = true
}
I checked the connections in the XML file.
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="country"
type="com.example.kotlincountries.model.Country" />
<variable
name="listener"
type="com.example.kotlincountries.adapter.CountryClickListener" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:onClick="#{listener::onCountryClicked}"
android:orientation="horizontal">
<TextView
android:id="#+id/countryUuidText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="#{String.valueOf(country.uuid)}">
</TextView>
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:padding="3dp"
android:downloadUrl="#{country.imageUrl}">
</ImageView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:layout_weight="3">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{country.countryName}"
android:padding="5dp"
android:textSize="18sp"
android:textStyle="bold">
</TextView>
<TextView
android:id="#+id/region"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{country.countryRegion}"
android:textSize="16sp"
android:padding="5dp">
</TextView>
</LinearLayout>
</LinearLayout>
</layout>
I checked the data I fetched in my adapter class.
class CountryAdapter(val countryList:ArrayList<Country>): RecyclerView.Adapter<CountryAdapter.CountryViewHolder>(),CountryClickListener {
private lateinit var binding : ItemCountryBinding
class CountryViewHolder(var view:ItemCountryBinding) :RecyclerView.ViewHolder(view.root) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CountryViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemCountryBinding.inflate(inflater, parent, false)
return CountryViewHolder(binding)
}
override fun getItemCount(): Int {
return countryList.size
}
override fun onBindViewHolder(holder: CountryViewHolder, position: Int) {
holder.view.country=countryList[position]
holder.view.listener=this
}
fun updateCountryList(newCountryList:List<Country>){
countryList.clear()
countryList.addAll(newCountryList)
notifyDataSetChanged()
}
override fun onCountryClicked(v: View) {
val uuid=binding.countryUuidText.text.toString().toInt()
val action=FeedFragmentDirections.actionFeedFragmentToCountryFragment(uuid)
Navigation.findNavController(v).navigate(action)
}
}
Could you please help me? I couldn't find a solution even though I checked the connections in my XML file, verified the data in my adapter class.

Error message is clear that binding variable which is declared as lateinit is not initialised and tried to use it in your adapter class .
and if you will check your code of adapter (as location mentioned in error) you will get that problem is in onCreateViewHolder
So just change in onCreateViewHolder method of adapter
From
val binding = ItemCountryBinding.inflate(inflater, parent, false)
To
binding = ItemCountryBinding.inflate(inflater, parent, false)
i have just removed val as you have already declared binding

Related

Can a Kotlin entity with a constructor that has default non null values become null at runtime?

I have spent the last couple of weeks trying to rewrite an android app from a java to kotlin, from custom fragment navigation to navigation component and all other Jetpack bells and whistles.
Now I've encountered several bugs through this process but there's this specific one. I have a kotlin class with a default constructor as shown below
#Entity(tableName = Globals.FIREBASE_ITEM_NODE)
#Parcelize
class Item(
#PrimaryKey(autoGenerate = true)
var id: Int = 0 ,
var imageUri: String = "",
var isRead: Boolean = false,
var expanded: Boolean = false,
var favourite: Boolean = false,
var isSaved: Boolean = false,
var englishWord: String = "",
var topic: String = "",
var audioUri: String = "",
var rutooroWord: String = "",
var firebaseImageNode: String = "",
) : Parcelable
This is because I fetch data from firebase rtdb and cache it in room. I then collect a flow of this data submit it to a List Adapter and use databinding to bind it to my views.
the item Viewholder
inner class ItemViewHolder(private val b: RvLangItemBinding) : RecyclerView.ViewHolder(b.root) {
fun bind(position: Int) {
if (getItem(position) !is Item) return
b.item = getItem(position) as Item
if ((getItem(position) as Item).expanded) createPalette(
(getItem(position) as Item).imageUri,
b.parent,
b.tvEnglish,
b.tvRutooro
)
else b.parent.setBackgroundColor(
itemView.context.resources.getColor(
R.color.transparent,
itemView.context.theme
)
)
b.root.setOnClickListener {
(getItem(position) as Item).expanded = !(getItem(position) as Item).expanded
notifyItemChanged(position)
if (prevPosition != INITIAL_POSITION && prevPosition != position) {
(getItem(prevPosition) as Item).expanded = false
notifyItemChanged(prevPosition)
}
prevPosition = position
if ((getItem(position) as Item).expanded && (getItem(position) as Item).audioUri.isNotEmpty())
AudioUtil.playAudioFile(
itemView.context,
Uri.parse((getItem(position) as Item).audioUri)
)
}
b.favourite.setOnLikeListener(object : OnLikeListener {
override fun liked(likeButton: LikeButton) {
(getItem(position) as Item).favourite = true
onItem.update(getItem(position) as Item)
}
override fun unLiked(likeButton: LikeButton) {
(getItem(position) as Item).favourite = false
onItem.update(getItem(position) as Item)
}
})
b.audioButton.setOnClickListener {
if ((getItem(position) as Item).audioUri.isNotEmpty())
AudioUtil.playAudioFile(
itemView.context,
Uri.parse((getItem(position) as Item).audioUri)
)
}
}
}
and this is the xml for the item
<?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>
<import type="android.view.View" />
<variable
name="item"
type="com.allez.san.learnrutooro.models.Item" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="18dp"
android:elevation="4dp"
android:padding="8dp"
app:cardCornerRadius="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
android:id="#+id/tv_english"
style="#style/TextAppearance.Material3.TitleMedium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="#{item.englishWord}"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="#id/favourite"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Good Morning" />
<com.like.LikeButton
android:id="#+id/favourite"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="4dp"
app:icon_size="25dp"
app:icon_type="star"
app:liked="#{item.favourite}"
app:layout_constraintBottom_toBottomOf="#+id/tv_english"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/tv_english"
app:like_drawable="#drawable/ic_star_green"
app:unlike_drawable="#drawable/ic_star_white" />
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="4dp"
android:background="#android:color/darker_gray"
app:layout_constraintBottom_toBottomOf="#id/downArrow"
app:layout_constraintEnd_toStartOf="#id/downArrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/downArrow" />
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/downArrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="#drawable/ic_arrow_drop_down"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/favourite" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/tv_rutooro"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="#{item.rutooroWord}"
android:textSize="16sp"
android:visibility="#{item.expanded? View.VISIBLE:View.GONE}"
app:layout_constraintBottom_toTopOf="#id/item_image"
app:layout_goneMarginBottom="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/downArrow"
tools:text="oraire ota" />
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/item_image"
setImage="#{item.imageUri}"
setImageItemVisibility="#{item}"
android:layout_width="270dp"
android:layout_height="200dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tv_rutooro"
app:layout_goneMarginBottom="16dp"
tools:src="#drawable/lr_logo_light" />
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/audio_button"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:src="#drawable/ic_audio"
android:visibility="#{item.expanded? View.VISIBLE:View.GONE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/downArrow"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>
and these are my binding adapters
#BindingAdapter("setImage")
fun setImage(view:ImageView, uri: String)=
Glide.with(view).load(uri).into(view)
#BindingAdapter("setImageItemVisibility")
fun setItemImageVisibility(view:ImageView, item: Item){
view.visibility = if(item.expanded && item.imageUri.isNotEmpty()) View.VISIBLE else View.GONE
}
and this is the error I've been getting.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.allez.san.myapplication, PID: 26721
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter item
at com.allez.san.learnrutooro.utils.BindingUtilsKt.setItemImageVisibility(Unknown Source:7)
at com.allez.san.learnrutooro.databinding.RvLangItemBindingImpl.executeBindings(RvLangItemBindingImpl.java:152)
at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:512)
at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:484)
at androidx.databinding.ViewDataBinding$7.run(ViewDataBinding.java:218)
at androidx.databinding.ViewDataBinding$8.doFrame(ViewDataBinding.java:320)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1106)
at android.view.Choreographer.doCallbacks(Choreographer.java:866)
at android.view.Choreographer.doFrame(Choreographer.java:792)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1092)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
I/Process: Sending signal. PID: 26721 SIG: 9
How is this possible and why??? I've been at it for a while now. reading as much as I could about the subject but no luck yet.
Any help will be appreciated. thanx in advance.
try to change the fields type to nullable and run it again, if you did not have the same error then the problem is that you defined entity all its fields are non-nullable, so when you are calling #Query("SELECT * FROM items") fun getAllItems(): Flow<List<Item>> you are trying to give a null value from database to one of the fields.
I think the problem was with my binding adapters
#BindingAdapter("setImage")
fun setImage(view: ImageView, uri: String) =
Glide.with(view).load(uri).into(view)
#BindingAdapter("setImageItemVisibility")
fun setItemImageVisibility(view: ImageView, item: Item) {
view.visibility = if (item.expanded && item.imageUri.isNotEmpty()) View.VISIBLE else View.GONE
}
Because when i switched to directly binding the image and setting the image visibility in the item viewholder everything is working just fine.
Glide.with(itemView).load((getItem(position) as Item).imageUri).into(b.itemImage)
b.itemImage.visibility = if ((getItem(position) as Item).expanded && (getItem(position) as Item).imageUri.isNotEmpty()) View.VISIBLE else View.GONE
I don't think this is a solution to that error coz I still don't know why I was getting it and I'd like to still use databinding to set the image and its visibility. If anyone has an explanation as to why this was happening I'd really appreciate it.

Crash with MoPubRecyclerAdapter and Facebook Native Ads in ConstraintLayout

Expected
The MoPubRecyclerAdapter is expected to inflate native Facebook RecyclerView cells using a defined ConstraintLayout.
Observed
Error
The MoPubRecyclerAdapter is crashing intermittently for ConstraintLayouts created from Facebook native ads. This issue has been noted in the MoPub SDK forum and MoPub Android Mediation GitHub repository.
Log
Fatal Exception: java.lang.ClassCastException: androidx.constraintlayout.widget.ConstraintLayout cannot be cast to android.widget.RelativeLayout
at com.mopub.nativeads.FacebookAdRenderer$FacebookNativeViewHolder.fromViewBinder(FacebookAdRenderer.java:139)
at com.mopub.nativeads.FacebookAdRenderer.renderAdView(FacebookAdRenderer.java:58)
at com.mopub.nativeads.FacebookAdRenderer.renderAdView(FacebookAdRenderer.java:28)
at com.mopub.nativeads.NativeAd.renderAdView(NativeAd.java:166)
at com.mopub.nativeads.MoPubStreamAdPlacer.bindAdView(MoPubStreamAdPlacer.java:433)
at com.mopub.nativeads.MoPubRecyclerAdapter.onBindViewHolder(MoPubRecyclerAdapter.java:424)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:366)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:397)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:205)
at android.app.ActivityThread.main(ActivityThread.java:6991)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884)
Implementation
facebook_native_ad_item.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:id="#+id/native_outer_view"
style="#style/AdContentCardStyle"
android:layout_width="match_parent"
android:layout_height="#dimen/cell_content_feed_height"
android:textDirection="locale">
<TextView
android:id="#+id/native_title"
style="#style/CellCreatorStyle"
app:layout_constraintBottom_toBottomOf="#+id/guideline"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/native_icon_image" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#id/native_media_view"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/sponsored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sponsored"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/guideline" />
<com.facebook.ads.AdIconView
android:id="#+id/native_icon_image"
android:layout_width="#dimen/native_icon_image_dimen"
android:layout_height="#dimen/native_icon_image_dimen"
android:paddingRight="#dimen/padding_tiny"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.facebook.ads.MediaView
android:id="#+id/native_media_view"
style="#style/AdCellPreviewImageStyle"
android:contentDescription="#string/native_main_image"
app:layout_constraintBottom_toTopOf="#id/native_text"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/sponsored" />
<TextView
android:id="#+id/native_text"
style="#style/CellTitleStyle"
app:layout_constraintBottom_toTopOf="#id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/native_media_view"
tools:text="#string/learn_more" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/native_ad_choices_relative_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="left"
app:layout_constraintBottom_toBottomOf="#id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#id/native_cta" />
<TextView
android:id="#+id/native_cta"
style="#style/NativeCtaStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/native_text"
tools:text="#string/learn_more" />
</androidx.constraintlayout.widget.ConstraintLayout>
SomeFragment.kt
adapter = FeedAdapter(feedViewModel, viewEvent)
moPubAdapter = MoPubRecyclerAdapter(
requireActivity(),
adapter,
MoPubNativeAdPositioning.MoPubServerPositioning())
moPubAdapter.registerAdRenderer(FacebookAdRenderer(
FacebookViewBinder.Builder(fb_native_ad_item)
.titleId(native_title)
.textId(native_text)
.mediaViewId(native_media_view)
.adIconViewId(native_icon_image)
.adChoicesRelativeLayoutId(native_ad_choices_relative_layout)
.advertiserNameId(native_title)
.callToActionId(native_cta)
.build()))
val viewBinder = ViewBinder.Builder(native_ad_item)
.titleId(native_title)
.textId(native_text)
.mainImageId(R.id.native_main_image)
.iconImageId(native_icon_image)
.callToActionId(native_cta)
.privacyInformationIconImageId(string.native_privacy_information_icon_image)
.build()
moPubAdapter.registerAdRenderer(FlurryNativeAdRenderer(FlurryViewBinder(Builder(viewBinder))))
moPubAdapter.registerAdRenderer(MoPubVideoNativeAdRenderer(
MediaViewBinder.Builder(fb_native_ad_item)
.mediaLayoutId(native_media_view)
.iconImageId(native_icon_image)
.titleId(native_title)
.textId(native_text)
.privacyInformationIconImageId(native_ad_choices_relative_layout)
.build()))
moPubAdapter.registerAdRenderer(MoPubStaticNativeAdRenderer(viewBinder))
moPubAdapter.setContentChangeStrategy(MOVE_ALL_ADS_WITH_CONTENT)
contentRecyclerView.adapter = moPubAdapter
FeedApater.kt
#ExperimentalCoroutinesApi
class FeedAdapter(val viewModel: FeedViewModel, val viewEvent: FeedViewEvent)
: PagedListAdapter<Content, FeedAdapter.ViewHolder>(DIFF_CALLBACK) {
class ViewHolder(private var binding: CellContentBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(viewModel: FeedViewModel, content: Content, onClickListener: OnClickListener) {
binding.viewModel = viewModel
binding.data = content
binding.clickListener = onClickListener
binding.executePendingBindings()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = CellContentBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
getItem(position)?.let { content ->
holder.bind(viewModel, content, createOnClickListener(content, position))
}
}
private fun createOnClickListener(content: Content, position: Int) = OnClickListener { view ->
}
Environments
Libraries
implementation("com.mopub:mopub-sdk-native-static:5.11.1#aar") { transitive = true }
implementation("com.mopub:mopub-sdk-native-video:5.11.1#aar") { transitive = true }
implementation 'com.facebook.android:audience-network-sdk:5.1.0'
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.1.0.0'
implementation 'com.flurry.android:ads:12.1.0#aar'
implementation 'com.flurry.android:analytics:12.1.0#aar'
implementation 'com.mopub.mediation:flurry:11.4.0.0'
Android levels
8.1.0
9
10
Devices
LG Q60
Pixel 3a
Redmi Note 5 Pro
Attempted solution
The library versions have been updated for the MoPub SDK to 5.12.0, the Facebook Audience Network to 5.8.0, and Facebook mediation to 5.8.0.0. It is to be determined whether this resolves the above crash.
implementation("com.mopub:mopub-sdk-native-static:5.12.0") { transitive = true }
implementation("com.mopub:mopub-sdk-native-video:5.12.0") { transitive = true }
implementation 'com.facebook.android:audience-network-sdk:5.8.0'
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.8.0.0'
Use RelativeLayout instead of ConstraintLayout
As MoPub's engineer points out in this GitHub issue, Facebook mediation is not yet compatible with ConstraintLayout.
AdChoices icon XML view (with the ID native_ad_choices_relative_layout) needs to be a RelativeLayout due to internal changes in the 4.99.0+ version of the Facebook Audience Network SDK. The adapter expects a RelativeLayout here.
Before
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/native_ad_choices_relative_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="left"
app:layout_constraintBottom_toBottomOf="#id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#id/native_cta" />
After
<RelativeLayout
android:id="#+id/native_ad_choices_relative_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="left" />
Documentation: Setup Ad Renderers for Native Ads
Sample: github.com/mopub/mopub-sdk-android

Binding variable is null.. How to let the observer in UI wait till the queried Livedata is excuted from database?

I am trying to get data from database and then bind it in fragment to the XML.
So I have repository getting the data from the DB to the ViewModel and the UI fragment is observing the results and then binding the data to the XML.
But the problem is that the app is crushing saying that data is null Even though I am voiding the null data in the observer.
I've tried the to execute the query on the background thread it seems to be working properly the returning the data (Photo).
I think the problem is that the query is taking time and the Observer in the fragment is not waiting till the query is done.
So the query is okay and I am following exactly Google samples but could not figure out the problem.
Thanks in advance.
_PhotoRepository
class PhotoRepository #Inject constructor(
private val photoDao: PhotoDoa
) {
fun loadPhotoById(photoId: Int): LiveData<Photo> {
// var photo: Photo? = null
// this is working and i am getting the photo object
// appExecutors.diskIO().execute {
photo = photoDao.getObjectPhotoById(photoId)
}
return photoDao.getPhotoById(photoId)
}
}
_PhotoViewModel
class PhotoViewModel #Inject constructor(private val photoRepository:
PhotoRepository) :
ViewModel() {
private var _photoId = MutableLiveData<Int>()
val photoId: LiveData<Int>
get() = _photoId
val photo: LiveData<Photo> = Transformations
.switchMap(_photoId) { id ->
photoRepository.loadPhotoById(id)
}
fun setId(photoId: Int) {
// if (_photoId.value == photoId){
// return
// }
_photoId.value = photoId
}
}
_PhotoFragment
class PhotoFragment : Fragment(), Injectable {
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
var binding by autoCleared<FragmentPhotoBinding>()
lateinit var photoViewModel: PhotoViewModel
var photo = Photo()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate<FragmentPhotoBinding>(
inflater,
R.layout.fragment_photo,
container,
false
)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val params = PhotoFragmentArgs.fromBundle(arguments!!)
photoViewModel = ViewModelProviders.of(
this,
viewModelFactory).get(PhotoViewModel::class.java)
photoViewModel.setId(params.photoId)
// photoViewModel.photo.removeObservers(viewLifecycleOwner)
photoViewModel.photo.observe(viewLifecycleOwner, Observer {
if (it != null) {
binding.photo = it
}
})
}
}
_ The Query in the Doa class
#Query(" SELECT * FROM Photo WHERE id = :id")
abstract fun getPhotoById ( id: Int): LiveData<Photo>
_ fragment_photo.xml
<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>
<import type="com.mustafa.pixabayapp.models.Photo"/>
<variable
name="photo"
type="Photo"/>
<import type="com.mustafa.pixabayapp.utils.StringUtils" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/photo_fragment_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:imageUrl="#{photo.webFormatURL}"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorTransparentDark"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="#+id/photo_fragment_tags"
style="#style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{StringUtils.getTags(photo.tags)}"
tools:text="TEST - TEST - TEST"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/photo_fragment_user_name"
style="#style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:text="#{StringUtils.byUser(photo.userName)}"
tools:text="By: Mustafa"/>
<TextView
android:id="#+id/photo_fragment_comments"
style="#style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="4dp"
android:drawableStart="#drawable/ic_comment"
android:text="#{StringUtils.getCommentsAsString(photo.commentsCount)}"
tools:text="2222"/>
<TextView
android:id="#+id/photo_fragment_favorites"
style="#style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_toStartOf="#id/photo_fragment_comments"
android:drawableStart="#drawable/ic_favorite"
android:text="#{StringUtils.getFavoritesAsString(photo.favoritesCount)}"
tools:text="2222"/>
<TextView
android:id="#+id/photo_fragment_likes"
style="#style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_toStartOf="#id/photo_fragment_favorites"
android:drawableStart="#drawable/ic_like"
android:text="#{StringUtils.getLikesAsString(photo.likesCount)}"
tools:text="2222"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</layout>
_The Error message:
java.lang.IllegalArgumentException:
Parameter specified as non-null is null:
method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter
userName at com.mustafa.pixabayapp.utils.StringUtils.byUser(Unknown
Source:2)at com.mustafa.pixabayapp.databinding.FragmentPhotoBindingImpl.
executeBindings(FragmentPhotoBindingImpl.java:138)
Yes, your assumption with "it takes time" is correct. The layout wants to draw something as soon its bind and at this time photo is not loaded yet.
You could handle the null value in StringUtils.byUser() or adding a null check in the layout like here: Data binding: set property if it isn't null

How to disable a button in Kotlin?

I have created 2 activities, well the first one I use it as splash screen, now in the second one I have difficulties when deactivating a button, I leave the code for your understanding
activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TemaCalcActivity">
<Spinner
android:layout_width="144dp"
android:layout_height="39dp"
android:id="#+id/spnDiferencia" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginStart="8dp" app:layout_constraintStart_toEndOf="#+id/spnMP"
android:layout_marginEnd="8dp" android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="#+id/textView5"/>
<Button
android:text="OK"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/button" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="120dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="120dp" android:layout_marginTop="32dp"
app:layout_constraintTop_toBottomOf="#+id/spnMP" android:background="#drawable/button_effect"
android:textSize="18sp" android:textStyle="bold" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.026" android:onClick="onBotonFinalizar" android:enabled="false"/>
</android.support.constraint.ConstraintLayout>
Main2Activity.kt
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
spnDiferencia.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
when (position) {
0 -> { button.isEnabled = true}
1 -> { button.isEnabled = false}
}
}
The error I have is that the entire application is stopped and then restarted, making this a repetition.
button.isEnabled = true
// or
button.isClickable = true
caution ---> button == btnCalcular
--- error log ---
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mrl.fr.tuto, PID: 22066
java.lang.IllegalStateException: btnCalcular must not be null
at com.mrl.fr.tuto.Main2Activity$onCreate$5.onItemSelected(Main2cActivity.kt:128)
at android.widget.AdapterView.fireOnSelected(AdapterView.java:919)
at android.widget.AdapterView.dispatchOnItemSelected(AdapterView.java:908)
at android.widget.AdapterView.access$300(AdapterView.java:53)
at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:878)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5631)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Just to disable a button .
button.isEnabled = false
button.isClickable = false
and If you want to disable a button , and want to grey out its color & background ,you can do something like this -
fun markButtonDisable(button: Button) {
button?.isEnabled = false
button?.setTextColor(ContextCompat.getColor(textView.context, R.color.white))
button?.setBackgroundColor(ContextCompat.getColor(textView.context, R.color.greyish))
}
Did you try this
myButton.setEnabled(false);

Android RecyclerView Adapter DataBinding - cannot find symbol {layout}BindingImpl

I have a Fragment that displays a list of cities with weather informations. I am using a RecyclerView and I am trying to implement the Data Binding Library in my RecyclerView Adapter but for some reason I get this compile error :
> error: cannot find symbol import
com.example.zach.weatherapp.databinding.CityListItemBindingImpl;
> ^
> symbol: class CityListItemBindingImpl
> location: package com.example.zach.weatherapp.databinding
It's an auto generated class so i really don't know where the error is. I had the same error previously for other layouts when there was someting wrong in the xml file but here it seems fine.
ForecastAdapter.kt
package com.example.zach.weatherapp.Adapter
import ...
class ForecastAdapter(var myDataset: List<City>) :
RecyclerView.Adapter<ForecastAdapter.ForecastViewHolder>() {
var context:Context?=null
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder.
class ForecastViewHolder(var binding: CityListItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(city: City){
binding.city = city
}
}
// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): ForecastAdapter.ForecastViewHolder {
context = parent.context
val layoutIdForListItem = R.layout.city_list_item
val inflater = LayoutInflater.from(context)
val shouldAttachToParentImmediately = false
val binding = DataBindingUtil.inflate<CityListItemBinding>(inflater,layoutIdForListItem,parent,shouldAttachToParentImmediately)
//val view = inflater.inflate(layoutIdForListItem, parent, shouldAttachToParentImmediately)
return ForecastViewHolder(binding)
}
// Replace the contents of a view (invoked by the layout manager)
override fun onBindViewHolder(holder: ForecastViewHolder, position: Int) {
val city = myDataset[position]
holder.bind(city)
Glide.with(context)
.load("http://openweathermap.org/img/w/${city.weather[0].icon}.png")
.into(holder.binding.forceastImageView)
holder.binding.container.setOnClickListener{ view: View ->
Timber.d("Clicked on city %s",city.name)
Navigation.findNavController(view).navigate(ListFragmentDirections.actionListFragmentToForecastDetailsFragment(city.id))}
}
// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = myDataset.size
}
city_list_item.xml
<?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="city" type="com.example.zach.weatherapp.data.City"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/container">
<TextView
tools:text="Caen"
android:text="#{city.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/city_name_textview"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent"
android:fontFamily="#font/roboto_light" android:textSize="22sp" android:textStyle="bold"
android:maxLines="1" android:ellipsize="end"/>
<TextView
tools:text="Sunny"
android:text="#{city.weather[0].description}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/city_forecast_textview" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="#+id/city_name_textview" android:fontFamily="#font/roboto_light"
android:layout_marginBottom="16dp" app:layout_constraintBottom_toBottomOf="parent"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp" app:srcCompat="#drawable/sunny"
android:id="#+id/forceast_imageView" android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintVertical_bias="0.562"
android:layout_marginEnd="32dp" app:layout_constraintEnd_toStartOf="#+id/temperatures_layout"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/temperatures_layout"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
tools:text="15°"
android:text="#{city.main.temp_max}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/max_temperature_textview"
android:fontFamily="#font/roboto_light"
tools:layout_editor_absoluteY="17dp" tools:layout_editor_absoluteX="313dp"/>
<TextView
tools:text="9°"
android:text="#{city.main.temp_min}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/min_temperature_textview"
android:fontFamily="#font/roboto_light" tools:layout_editor_absoluteY="45dp"
tools:layout_editor_absoluteX="321dp" android:layout_gravity="right"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
It might just be an Android Studio error because the xml file seems fine.
UPDATE :
Error seems to come from Xml. I removed the android:text="#{city.xxx}" in my xml layout and instead updated my textViews manually in my ViewHolder bind method like so :
fun bind(boundCity: City){
with(binding){
cityNameTextview.text = boundCity.name
cityForecastTextview.text = boundCity.weather[0].description
maxTemperatureTextview.text = "${boundCity.main.temp_max}°"
minTemperatureTextview.text = "${boundCity.main.temp_min}°"
Glide.with(root.context)
.load("http://openweathermap.org/img/w/${boundCity.weather[0].icon}.png")
.into(forceastImageView)
container.setOnClickListener{ view: View ->
Timber.d("Clicked on city %s",boundCity.name)
Navigation.findNavController(view).navigate(ListFragmentDirections.actionListFragmentToForecastDetailsFragment(boundCity.id))}
}
}
And I no longer get the error. The error comes whenever I add android:text="#{city.xx}" in my textviews and bind the city variable in the bind method. I still don't know why though....
This should work for you I believe;
class ForecastAdapter(private var myDataset: List<City>) : RecyclerView.Adapter<ForecastAdapter.ForecastViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ForecastAdapter.ForecastViewHolder {
val itemBinding = CityListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ForecastViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: ForecastViewHolder, position: Int) {
val city = myDataset[position]
holder.bind(city)
}
override fun getItemCount() = myDataset.size
inner class ForecastViewHolder(var binding: CityListItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(boundCity: City){
with(binding) {
city = boundCity
Glide.with(root.context)
.load("http://openweathermap.org/img/w/${city.weather[0].icon}.png")
.into(forceastImageView)
container.setOnClickListener { view ->
Timber.d("Clicked on city %s", city.name)
Navigation.findNavController(view).navigate(ListFragmentDirections.actionListFragmentToForecastDetailsFragment(city.id))
}
}
}
Hey you could try adding the following line after the <data> tag :
<import type="android.view.View" />
I found that worked for me when I had that error.

Categories

Resources