how to create class of findViewById? - android-studio

I am a beginner ,https://i.stack.imgur.com/k8z9T.jpgin the android studio whenever I try to use findViewById.It shows an error and they ask me to create its variable but I don't know how to create it . Please tell me, I am stuck here.

You just created a function outside of your MainActivity. You have to create it inside of your activity. According to your screenshot, you just try to create a Top-level Function not a Function because it's outside of your activity. When you need to create a Function you have to create that inside your activity. Keep your eyes on Curley Brackets {}.
See the explanation to understand.
In your screenshot
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
} /* Your activity end's on here*/
private fun addNickName(view: View) {
// Your instance
// val editText = findViewById<EditText>(R.id.nickName_edit)
}
So the answer is
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
private fun addNickName(view: View) {
// Your instance
// val editText = findViewById<EditText>(R.id.nickName_edit)
}
} /* Your activity end's on here*/
Hope you understand!. Thank you

Related

Hilt - cannot be initialized ViewModelFactory in fragment

i'am using retrofit library to get info from internet api , then i put the data in the repository then get it in viewmodel which it will be instatiate by viewmodelfactory ;
so i'am trying to inject HitViewModelFactory by using Dagger-Hilt in Fragment but it show me an error when to inject it in the fragment
lateinit property hitViewModelFactory has not been initialized
i make an application class and anotate it with #HiltAndroidApp and give the name of application in manifest. and make anotate to activity that host this fragment but the problem not solved
#AndroidEntryPoint
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
.......
}
}
i provide all dependencies that i need in the module class :
#Module
#InstallIn(ApplicationComponent::class)
object AppModule {
#Singleton
#Provides
fun provideHitPhotoApi() = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(HitApi::class.java)
#Singleton
#Provides
fun provideHitRepository(hitApi: HitApi) = HitRepository(hitApi)
#Singleton
#Provides
fun provideHitViewModelFactory(hitRepository: HitRepository) : HitViewModelFactory = HitViewModelFactory(hitRepository)
}
and try to inject ViewModelFactory in this fragment
#AndroidEntryPoint
class TripsFragment : Fragment() {
#Inject
lateinit var hitViewModelFactory: HitViewModelFactory
lateinit var hitViewModel: HitViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hitViewModel = ViewModelProvider(requireActivity(),hitViewModelFactory)[HitViewModel::class.java ]
}
dependency for hilt :
Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-
alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
I also faced same issue earlier. Not sure why this fails but it seems code is correct.
So I have done with different approach.
I created view model like this below. And I inject HitApi directly in viewmodel constructor. Then just initialize like below. It takes care of creating viewmodel instance and hilt takes care of injection.No need of creating factory.
ViewModel:
#HiltViewModel
class HitViewModel #Inject constructor(
var api: HitApi) : ViewModel() {
}
Fragment:
#AndroidEntryPoint
class TripsFragment : Fragment() {
private val viewModel by viewModels<HitViewModel>() //No need of inject annotation.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
Make sure you have these dependancies.
//For activity
implementation 'androidx.activity:activity-ktx:1.5.1'
//For fragment
implementation 'androidx.fragment:fragment-ktx:1.5.1'
the problem solved when i change the dependency of Hilt to :
implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-compiler:2.38.1"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
and for these dependencies it should replace the InstallIn anotation for module class to SingletonComponent::class like
#Module
#InstallIn(SingletonComponent::class)
object AppModule { ... }

findViewById keeps giving me errors and a headache

Hello all,
I am new to Kotlin and was trying to keep recreating my code to get it easier for me to learn. i have created an dice app and it works. but everytime i create a new project and start. I always get the error on findViewById(R.id.) i make the layout first with all the ID`s assigned but no matter what i do i keep getting this error. I use Android Studio.
I hope someone can help me get this frustration out of my head.I want to know why it keeps getting that error. thanks in advance.
package com.example.dicedicebaby
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//button action`
val rollButton: Button = findViewById(R.id.button)
//action of the button when pressed.
rollButton.setOnClickListener{ stones()}
}
}
fun stones(){
//The normal dice
val fDice=Dice(6)
//D20
val dDice = Dice(20)
//action of dice roll
val dice = fDice.roll()
//D20 action
val secondDice = dDice.roll()
//view
val resultView: TextView = findViewById(R.id.dice)
resultView.text = dice.toString()
val secondView: TextView = findViewById(R.id.Ddice)
secondView.text = secondDice.toString()
}
//makes the dice a dice.
class Dice(private val numSides:Int){
fun roll():Int{
return (1..numSides).random()
}
}
The suggested approach is to migrate to view binding.
Plus, you should declare the stones() function inside the MainActivity class body:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//action of the button when pressed.
binding.rollButton.setOnClickListener{ stones() }
}
fun stones(){
//The normal dice
val fDice=Dice(6)
//D20
val dDice = Dice(20)
//action of dice roll
val dice = fDice.roll()
//D20 action
val secondDice = dDice.roll()
//view
binding.dice.text = dice.toString()
binding.Ddice.text = secondDice.toString()
}
}

How can I preview a Compose view when it need a parameter in Android Studio?

I can run Code A in Android Studio, I hope to preview UI when I'm designing, so I added Code B to Code A.
But Code B can't work, why? How can I fix it?
Code A
class MainActivity : ComponentActivity() {
private val handleMeter by viewModels<HandleMeter>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(handleMeter)
}
}
}
}
}
#Composable
fun Greeting(handleMeter: HandleMeter) {
...
}
Code B
#Preview(showBackground = true)
#Composable
fun DefaultPreview() {
SoundMeterTheme {
val handleMeter by viewModels<HandleMeter>()
Greeting(handleMeter)
}
}
Unfortunately, you can't.
Preview does not support creating ViewModels and NavHost yet, for our bad.
But what you can do instead is to use a fake data or a static data into ui, until the design finish and when you are ready to actually run it, replace the static data with the view model data.
You can use dagger and hilt to inject the view model constructor and then call up the hilt view model in the preview e.g.
#HiltViewModel
class DataFieldsViewModel #Inject constructor(
) : ViewModel() {
Then in your preview code for your composable
#Preview(showBackground = true)
#Composable
fun PreviewDataFieldsScreen() {
DataFieldsScreen(
navController = rememberNavController(),
viewModel = hiltViewModel()
)
}

findViewById() unresolved reference in codelabs

Good day, y'all!
Today I was doing the Google Codelabs for Kotlin. I'm trying to use findViewById() in a function but it shows as an unresolved reference. I bet it's a fairly easy problem but I can't figure it out. this is my code
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.done_button).setOnClickListener { addNickname(it) }
}
}
private fun addNickname(view: View) {
val editText = findViewById<EditText>(R.id.nickname_edit)
val nicknameTextView = findViewById<TextView>(R.id.nickname_text)
nicknameTextView.text = editText.text
nicknameTextView.visibility = View.VISIBLE
editText.visibility = View.GONE
view.visibility = View.GONE
}
When I try to assign the editText and the nickmaneTextView vals to the views I use findViewById() but it shows as unresolved reverence.
it's quite basic so I don't know where is the issue
I'll be very grateful for your help
Edit:
if I use
val editText = view.findViewById<EditText>(R.id.nickname_edit)
val nicknameTextView = view.findViewById<TextView>(R.id.nickname_text)
I get an error saying that the nicknameTextView is null and it crashes
You should add view
val editText = view.findViewById<EditText>(R.id.nickname_edit)
val nicknameTextView = view.findViewById<TextView>(R.id.nickname_text)
Ok I figured it out, the fun must be created inside the
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
'here'
}
I knew it was a dumb problem :(
Thank you for your help

"lateinit" or "by lazy" when defining global android.widget var/val

When defining a global android.widget variable, e.g. TextView, is it preferable to use lateinit or by lazy? I initially thought using by lazy would be preferred as its immutable but I'm not entirely sure.
by lazy example:
class MainActivity: AppCompatActivity() {
val helloWorldTextView by lazy { findViewById(R.id.helloWorldTextView) as TextView }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
updateTextView(helloWorldTextView)
}
fun updateTextView(tv: TextView?) {
tv?.setText("Hello?")
}
}
lateinit example:
class MainActivity: AppCompatActivity() {
lateinit var helloWorldTextView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
helloWorldTextView = findViewById(R.id.helloWorldTextView) as TextView
updateTextView(helloWorldTextView)
}
fun updateTextView(tv: TextView?) {
tv?.setText("Hello?")
}
}
Are there any benefits of using one over the other when defining a global android.widget var/val? Are there any pitfalls with using by lazy to define a android.widget val? Is the decision just based on whether you want a mutable or immutable value?
There's one pitfall with by lazy. The widget property would be read-only and therefore technically final (in Java terms). But there's no documented guarantee that onCreate() is called only once for an instance. Also findViewById() could return null.
So using lateinit is preferable and you'll get an exception to tell you if the val was used before onCreate().
A third possibility would be Android synthetic properties. Then you don't need to worry about the variables at all.
import kotlinx.android.synthetic.main.activity_main.*
helloWorldTextView.text = "Hello?"

Resources