Android studio kotlin, cannot directly select ID without findViewById() - android

I'm new to android studio and I'm leaning it from this video
At 50:45 he says that we can directly use the id without findViewById (), for him it shows just import that Id, but when I tried the same I'm not getting what he is getting. Can anyone tell me what's wrong, is that feature removed in the latest update??

"kotlinx.android.synthetic is no longer a recommended practice. Removing in favour of explicit findViewById"
So, this feature`s been deprecated almost a year ago.
The new recommended way of working with view tree is View Binding.
Or you could write some lazy extension function that uses findViewById under the hood.

You can use the Kotlin Android Extensions check here or with the help of data binding or view binding you can just use the id directly in to your java activity class

The way you're talking about is Kotline Extensions for view, for which you apply it in the build.gradle file using apply plugin: 'kotlin-android-extensions', sync the project as prompted by the Android studio and it starts working.
But, Kotlin extensions has also been deprecated for view binding which is null-safe, also easy to implement and better.
To read about view binding, read the Android documentation on ViewBinding here and about migrating here. You can also go with this article to help with setting up Android view binding.

Related

AndroidStudio] Objects in layout file is not showing in the code [duplicate]

I am following a tutorial exactly. I gave the view a name in the layout XML file under android:id. When I type that name in Kotlin, it is highlighted in red and there is an "unresolved reference" error.
For example, in XML activity_main.xml:
<TextView
android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
In Kotlin MainActivity.kt:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
nameTextView // <-- This is highlighted red with error so I can't use it!
}
I created this question because I've seen variations of it several times since the deprecation of Kotlin Android Extensions, but they are all phrased in various ways and are not very searchable. I think the common factor is a new Android programmer following a tutorial that was written before the deprecation. These tutorials generally don't specify that the feature being used is called synthetic properties or Kotlin Android Extensions, synthetic view properties, or kotlin-android-extensions, and that the feature is deprecated.
The ability to refer to a view directly by it's ID/name in Kotlin is called "synthetic properties" and it is a feature of a project plugin called Kotlin Android Extensions.
Google and JetBrains decided to deprecate Kotlin Android Extensions, meaning they no longer support it, and discourage you from using it. Ever since it was deprecated, when you create a new project in Android Studio, the plugin is no longer included in the new project. Therefore, synthetic properties are not supported in new projects and you will get an "unresolved reference" error if you try to use it.
Tutorials written between 2017 and 2020 often make use of this feature, and if they haven't been updated, they probably don't even mention it by name, because it was taken for granted to be an included plugin in new projects.
Google explained the reasons for deprecating it in this blog post, with these key reasons:
They pollute the global namespace
They don’t expose nullability information
They only work in Kotlin code
The quick and easy way to get your view reference is to use findViewById. The type of View should go inside the brackets <>. In an Activity, it looks like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val nameTextView = findViewById<TextView>(R.id.nameTextView)
// Now you can refer to the view using the variable
nameTextView.setText(R.string.hello_world)
}
In a Fragment, you would probably be working with the view in the onViewCreated function, so you must call findViewById on the parent view. (If you need to access it elsewhere in the Fragment, use requireView() instead of view.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val nameTextView = view.findViewById<TextView>(R.id.nameTextView)
//...
}
findViewById is probably the best option for now if you just want to complete your tutorial that was written before Kotlin Android Extensions was deprecated.
However, using findViewById can be tedious, and it is also error prone, because it won't warn you if you are searching for a view that isn't in the current layout. If you do, it will crash at runtime. For this reason, Google recommends using View Binding. There are a few steps to get started with view binding, but once you set it up, it is a cleaner option than findViewById. The official instructions are here.
Finally, if you really don't care that Kotlin Android Extensions is deprecated and want to use it anyway, it currently still works OK, but you have to add the plugin to your new project to enable it. (Beware this will no longer work in Kotlin 1.8 and up.) To do that, open the build.gradle file for your app module. At the top in the plugins block, you can add a line for kotlin-android-extensions, like this:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
}
Then press the "Sync project with Gradle files" button in the toolbar to enable it.
You can't directly access the view ids.
But you can use:
Jetpack as Kotlin Android Extensions are deprecated. Source Kotlin Android Extensions Deprection
You can use view binding. View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module.
Source: View Binding

Kotlin synthetic imports doesn't work and it's now deprecated

In kotlin to access an element in the layout you do not need to do:
val k = findViewById(R......)
The element should be automatically imported into the kotlin file that connected to the view F.E if you have a text element in your main activity, in kotlin you access it by using it's id directly in the file that inflates that view and the import should be added automatically like this.
import kotlinx.android.synthetic.main.activity_main.view.*
However in few recent projects I noticed that this does not happen automatically.
You are correct, the Kotlin synthetics have quite a lot of similarities to the View Binding feature. The main advantage view binding has is that it's a bit harder to use the wrong binding class (with synthetics, you could quite easily import the wrong synthetics class if you have views in multiple layouts with the same ID).
I believe it's deprecated for a number of reasons, namely the type safety issue and the fact that it doesn't work with Java.
I've wrote a short tutorial on view binding here.
After some digging I found that Kotlin Android Extensions is now deprecated. Here is the guide to use the new method.
https://developer.android.com/topic/libraries/view-binding
Another option is to add the plugin in the app.gradle file.
plugins {
...
id 'kotlin-android-extensions'
}
After doing this two questions comes to mind:
Why did they remove the imports?
isn't the method that they demonstrated just doing the exact same thing as in it's importing the whole view?

Android Studio - MainActivity.kt doesn't recognise any element by ID

I'm struggling with very common problem, I think.
I've created a button in xml file and tagged it with ID. Then I wanted to make onClickListener in MainActivity.kt. But when I'm typing button's ID, it's marked red and it seems like Android Studio doesn't recognise it. I've tried cleaning and rebuilding project, but the problem still exist. Invalidate Caches/Restart didn't help as well.
There are screens from Android Studio.
View from XML
View from MainActivity.kt
Thanks for your time and help!
If you want to use synthetic view bindings by Jetbrains, you need to make sure to add kotlin-android-extensions plug-in your module gradle file.
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions' }
Stefan's answer above correcty states its considered obsolete now, but you can still use it. Or, again as in his answer, use findViewById.
Alternatively, you can use view bindings. For this, make sure to have this entry inside your Android section in your gradle file:
buildFeatures{
viewBinding = true
}
Refer to https://developer.android.com/topic/libraries/view-binding for how to use it.
What you are trying to do is using synthetic view bindings in Android Studio. As far as I found online, they are not recommended anymore. Use findViewById instead:
val button = findViewById<Button>(R.id.SUB_button)
button.setOnClickListener { ... }

Android Architecture Components

I am using MVVM android architecture for my application.
I want to implement click event, so, do we need to use data binding architecture components or we can just use activity for handling the click event and validating the user inputs?
What's the best way to implement this?
Well the question would be using the Databinding or not. Here are some pros and cons of Databinding:
Pros:
Makes the code super clean.
Makes the code shorter.
Easy to test.
Cons:
Sometimes it's hard to debug.
It's a little heavy and increases the compile time.
But... since Google has already anounced it as part of the Android Architecture components I believe you should use it.
What's the best way to implement this?
I don't know how familiar you are with the Databinding but you should know something about Binding Adapters, anw in the onClick you won't be needing it. Just add the android:onClick attribute in the XML file. Also you can find this Codelab to properly implement it:
https://codelabs.developers.google.com/codelabs/android-databinding/#0
Example:
First of all make sure you have the Databinding enabled in your build.gradle
android {
...
dataBinding {
enabled true
}
}
After that go to the layout you will use the databinding (and for that make sure it will be an Activity/Fragment), and just type ALT+ TAB in your IDE and than....
After that, define types, for example a ViewModel and it's name. And in the view that will use the click function add what I said above. (android:onClick="#{() -> viewmodel.onLike()}")
You are not finished. You will somehow need to connect your logic to that databinding, so go to your Java/Kotlin code for your Activity/Fragment and:
Replace the setContentView(R.layout.some_activity) with val binding : SomeActivityBinding =
DataBindingUtil.setContentView(this, R.layout.some_activity)
Notice the SomeActivityBinding will be provided by the IDE itself because is handled on the Databinding library according to the xml naming.
That's the most basic. Good luck.

Is there an eclipse plugin to generate findViewById calls?

I use eclipse for android development, and I find it very annoying that every time I create an activity or add new views to my activity, I need to create the references to views in my layout. I am looking for some kind of eclipse plugin that can generate the calls to findViewById() from the layout. I couldn't really find anything because I didn't know what it would be named. It would be very useful and time saving if that kind of plugin existed.
EDIT: The answers you gave are great. Can these tools also add more references to an existing activity so I don't have to manually do that when I add a view to the layout?
You can use https://github.com/JakeWharton/butterknife library for View Injections.
You can also get eclipse plugin https://marketplace.eclipse.org/content/lazy-android for the same.
But the ButterKnife library is frequently being contributed by android devs than the mentioned eclipse plugin. With this library, you can also avoid instantiating listeners yourself by just using like,
#OnClick(R.id.submit) void submit() {
// TODO call server...
}
For View injections, simply,
#InjectView(R.id.user) EditText username;
#InjectView(R.id.pass) EditText password;
So, it will compile as,
username = (EditText) findViewById(R.id.user);
password = (EditText) findViewById(R.id.pass);
Try the morcinek code generator. Its really simple to use.
This are the steps to install the plugin:
http://tmorcinek.wordpress.com/2011/11/30/eclipse-plugin-for-automatic-generation-of-activity-code-from-xml-layout-file/
After install process you may want to configurate a package to get the classes built by the generator, on the IDE -> Window -> Preferences on Bookmark Android Code Generator you can change that parameter.
The plugin does need a better interface for custom activities, still you could get the code, its really simple to make the changes you need, at least the inline listeners.
This solution doesnt work to modify classes you already have, that would be a really good improvement... i'll give it a try in a couple days with more time.

Categories

Resources