Databinding, Binding class can't find RealmObjects - android

I was using databinding with realm objects and after updating android studio and gradle the auto generated Binding classes can't find the RealmDb classes or directory.
I tried removing the realm object out of the databinding but the project won't override the existing auto generated class and i keep getting the same error.
This is how i'm binding the data
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate(inflater, R.layout.fragment_article_info, container, false) as FragmentArticleInfoBinding
val view = binding.root
viewModel = ArticleInfoVM(arguments?.getInt(KEY_ARTICLE_ID)!!)
binding.article = viewModel?.article.get()
return view
}
Why isn't the project able to find the classes?

Sometimes Android Studio has not found directories, if are there any error about different issues.
You can try to delete "RealmDB" package and clean All project then retry to insert emtyp RealmDB package. If are there any error, fix in order.

Related

Espresso launchFragmentInContainer<> binding issue

I have a simple test function like this:
#Test
fun testfunc() {
val fragScenario = launchFragmentInContainer<MyFragment>()
}
launchFragmentInContainer provides me with this error:
Binary XML file line #10: Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f040004 a=-1}
Caused by: java.lang.UnsupportedOperationException
which takes me to something wrong with the binding inflater.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = MyFragmentBinding.inflate(inflater, container, false)
return binding.root
}
I assume view binding doesn't work with isolated fragments like this? Do I need to create an entire new fragment without view binding just for testing?
In the fragment testing documentation there is a note:
Note: Your fragment might require a theme that the test activity doesn't use by default. You can provide your own theme as an additional argument to launch() and launchInContainer().
This error normally occurs when there are style values that the activity isn't aware of. Be sure to pass your app or fragment style via the themeResId parameter.

Android Dev in Kotlin, confused by tutorial

Im struggling with one of the android basics in kotlin code labs. Im a beginner who took up programming in lockdown for fun.
This is the tutorial in question
At the begining of the tutorial it says to get a nullable reference to binding named_binding, then use
private val binding get() = _binding!!
to get a version of it we can refer to without using the ? null safety thing. All good so far.
However in step four it shows the following code:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentLetterListBinding.inflate(inflater, container, false)
val view = binding.rootreturn view}
Why do we refer to _binding to inflate the view then binding in the next line when assigning the view?
Why do we refer to _binding to inflate the view then binding in the next line when assigning the view?
Two concepts to understand here.
_binding is considered a backing property - that is, the actual variable reference that holds a value. In this case, the variable is a nullable type.
binding is a standard property - that is, a thing that provides access to an underlying backing field. In this case, it's using _binding as a backing property as a minor convenience to expose _binding as a non-null.
So - since binding just exposes _binding as a non-null value, _binding must be set first. So that's why it's assigned the value of the inflate call. Also note that _binding is a var which means it can be re-assigned while binding is a val which means it can't. So trying to use binding when inflating the view would not compile.
Finally, why they use binding to get the view is unclear. Probably just for the sake of the convenience / consistency of using binding as the single property to reference the class binding. Using _binding?.root would work fine too.
This is best practice to protect someone modify _binding like _binding = null and you got error when access to _binding,
You should use binding.root instead _binding.root

ViewBinding - Included Layout Binding Resulting in Unresolved Reference

I am implementing ViewBinding in one of my fragments. This fragment has a layout included like so:
...
<androidx.core.widget.NestedScrollView
android:id="#+id/sv_sudf_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/btn_sudf_continue"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/eav_sudf_avatar">
<include
android:id="#+id/l_sudf_details"
layout="#layout/layout_sign_up_details_fields"/>
</androidx.core.widget.NestedScrollView>
...
I have followed this answer but it also does not work.
The generated view binding class for the fragment has the binding inside, however, the type for the attribute is View. When I then reference the View using binding.lSudfDetails the type is LayoutSignUpDetailFieldsBinding. Where this type is coming from I can't work out as there is no generated class with that name however, I would expect it would assign it the proper binding type. Here is the attribute in the FragmentSignUpDetailsBinding.java.
#NonNull
public final View lSudfDetails;
The bindings are all correctly setup however and it allow me to reference views within the nested layout but when I come to build I get unresolved reference errors. Lint does not complain when I reference them like this:
binding.lSudfDetails.etSudfDob
The compiler does fail however with errors such as this
Unresolved reference: etSudfDob
The binding itself is created according to the Android docs:
private var _binding : FragmentSignUpDetailsBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentSignUpDetailsBinding.inflate(inflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvSudfWelcome.text = getString(R.string.sign_up_welcome,getString(R.string.app_name))
binding.lSudfDetails.etSudfDob.setOnClickListener {
showYearSelection()
}
}
The tvSudfWelcome binding works its the nested binding it doesn't like.
If you're using Android Studio 3.6.0 sometimes gradle plugin fails to generate ViewBinding fields for included layouts. Please update to Android Studio 3.6.1 and gradle plugin version to 3.6.1.
If someone has similar problem... I solved my problem with adding width and height for this included view. It helped, I do not have any idea why, but this would be my solution:
<include
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/l_sudf_details"
layout="#layout/layout_sign_up_details_fields"/>
If someone has a similar problem - I solved mine using:
execute gradle task : prepareKotlinBuildScriptModel
changing the id name to the same as the layout name worked for me.
For eg:
<include
android:id="#+id/layout_sign_up_details_fields"
layout="#layout/layout_sign_up_details_fields"/>
I was working with databinding instead of viewbinding though

DataBindingUtil inflates layout as null

I am developing a single activity application using the Android Jetpack navigation component. On one of the fragments I utilize the built-in data binding tools. Strangely enough, even though it was working just the week before, it just completely broke today for seemingly no reason.
The setup:
The fragment I use with binding has the following layout file:
<?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>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/example_layout_root"
tools:context=".example.ExampleFragment"
android:background="#color/main_1"
>
...
</ScrollView>
</layout>
I have stripped the main content but it shows that I have a <layout> element as the root with both the data and the fragment layout part defined.
The fragment code is the following:
class ExamleFragment : Fragment() {
private val viewModel: ExampleViewModel by sharedViewModel()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val binding : FragmentExampleBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_example, container, false)
// This one also does not work
// val binding = FragmentExampleBinding.inflate(inflater, container, false)
binding.vm = viewModel
binding.lifecycleOwner = this
return binding.root
}
}
I use Koin to inject the viewmodel into the fragment.
When I try to inflate the layout (either with DataBindingUtil or the generated FragmentExampleBinding class) it results in the following exception:
java.lang.IllegalStateException: FragmentExampleBin…flater, container, false) must not be null at
com.example.fragments.ExampleFragment.onCreateView(ExampleFragment.kt:38)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at ...
And the stack goes straight down into OS territory so basically it doesn't give any useful information. I can't figure out why the result is null.
What I have tried:
I have tried inflating the layout with inflater.inflate(...) and it
works just fine but that way I can't use the data bindings.
I have tried removing EVERYTHING from the layout description that's
not absolutely neccessary and it still does not work.
I have tried reverting to previous commits (as far back as the first
working version with binding) and even though it used to work before,
it does not work now.
I even restarted and reset the emulator, tried different images, but
to no avail.
Has anyone encountered anything similar to this? The code really 'broke' over the weekend as I have just tested it the Friday before and it worked properly.
EDIT:
Okay, so I somehow managed to fix it.
I started experimenting with creating another fragment with data binding to see whether things are broken for all fragments or just that specific one. The new one seemed to work just fine but strangely, the old, broken fragment still refused to work even though they were basically the same.
So I did Clean + Rebuild (which I swear I performed as a first attempt to fix the issue) and it kind of just fixed it.
In my multi-module project, the reason for this problem was the fact that there was some kind of package name clash.
If you are getting this error without an apparent reason, double check the AndroidManifest.xml files of your data binding enabled modules.
Making sure all of the data binding enabled modules use unique package names solved the problem for me.
I spent hours to find the root of this problem hopefully others read this answer and won't spend that much.
Dont use DataBindingUtil for fragments, run your app once and android studio will generate a binding class for that fragment based off the name of your xml file, in your case the xml file is call fragment_example, so the class generated will be FragmentExampleBinding, then you call FragmentExampleBinding.inflate(....) like this:
val binding = FragmentExampleBinding.inflate(inflater, container, false);
Do it this way :
class ExamleFragment : Fragment() {
private val viewModel: ExampleViewModel by sharedViewModel()
lateinit binding:FragmentExmaple
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_example, container, false)
binding.vm = viewModel
binding.lifecycleOwner = this
return binding.root
}
}
please I need you to paste your error here
in my case I just forgot to add #AndroidEntryPoint to my fragment class

Can't access EditText or other UI components with Kotlin

I'm using Android Studio 3.0 RC2 & Kotlin.
When I try to access a UI component the app crashes unless I first write findViewById. I thought Kotlin was supposed to get rid of having to write findViewById line? The UI is a fragment and I'm trying to access from the same fragment code. Is there a way to not have to write findViewById?
These lines work:
var userNameField = view?.findViewById<EditText>(R.id.userNameTextField) as EditText
userNameField.setText("hello world")
This line doesn't work without findViewById line
userNameTextField.setText("hello world")
I even have
import kotlinx.android.synthetic.main.fragment_sign_in.*
The onCreateView() code:
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater!!.inflate(R.layout.fragment_sign_in, container, false)
var userNameField = view?.findViewById<EditText>(R.id.userNameTextField) as EditText
userNameField.setText("hello world")
return view
}
In the onCreateView just return the inflated view.
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater!!.inflate(R.layout.fragment_sign_in, container, false)
}
In the onViewCreated you can access your view components
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
userNameField.setText("hello world")
}
I was brought here by searching for the same issue. I missed to add the kotlin-android-extensions to the build.gradle:
apply plugin: 'kotlin-android-extensions'
Was unable to access the ui components like OP faced looks like below was needed inside app gradle:
plugins {
...
id 'kotlin-android-extensions'
}
Even though after adding this line android studio was still not able to auto resolve the imports for kotlin synthetics so you may need to invalidate cache and restart.
If still not working then import manually depending on views
activity /fragment view: import
kotlinx.android.synthetic.main.<your_activity_view>.*
normal views :
import kotlinx.android.synthetic.main.<your_layout_view>.view.*
I faced a similar problem.
I had a private function. I'd also imported the kotlinx library. But I was not able to access the editText from that function.
I just removed the function and defined it again.
Voila! It worked.
For those who have this problem in 2021:
I know this question is asked in the past but since it is still relevant here I want to help others:
today I ran to this problem and tried the suggested ways and unfortunately, the
plugins { ... id 'kotlin-android-extensions' }
is not working anymore or more accurately is deprecated, so try to use the Jetpack view binding approach and you'll be good.
The message I got after adding the Gradle Kotlin Android extension dependency is:
The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (click here) to start working with View Binding. (click here) and the 'kotlin-parcelize' plugin.

Categories

Resources