Issue
I am trying to add a listener to my button from a Fragment but it always give me this error:
Process: com.example.projectdrivemark, PID: 27776
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.projectdrivemark/com.example.MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3341)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3485)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2045)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7478)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
at com.example.tempConverter.TempConverterFragment.<init>(TempConverterFragment.kt:16)
at com.example.MainActivity.onCreate(MainActivity.kt:28)
at android.app.Activity.performCreate(Activity.java:7989)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3316
Here is MainActivity code:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.projectdrivemark.R
import com.example.projectdrivemark.databinding.ActivityMainBinding
import com.example.recyclerView.MockDatabase.Companion.createMockData
import com.example.recyclerView.PostAdapter
import com.example.recyclerView.RecyclerViewFragment
import com.example.tempConverter.TempConverterFragment
import com.example.uploaderView.UploaderFragment
class MainActivity : AppCompatActivity(), PostAdapter.OnPostClickListener {
private lateinit var binding: ActivityMainBinding
val dummyList = createMockData()
val adapter = PostAdapter(dummyList, this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
title = "First Kotlin App"
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val recyclerView = RecyclerViewFragment()
val tempConverterView = TempConverterFragment()
val uploaderView = UploaderFragment(this)
setFragmentView(recyclerView)
binding.bottomNavBar.setOnNavigationItemSelectedListener {
when(it.itemId){
R.id.listView -> setFragmentView(recyclerView)
R.id.tempConverterView -> setFragmentView(tempConverterView)
R.id.videoUploaderView -> setFragmentView(uploaderView)
}
true
}
}
private fun setFragmentView(fragment: Fragment){
supportFragmentManager.beginTransaction().apply {
replace(R.id.main_fragment_view, fragment)
//Will return to previous page when tap "Back Button" on the phone
addToBackStack(null)
commit()
}
}
override fun onEditPost(position: Int){
val clickedPost = dummyList[position]
clickedPost.title = "Updated title"
clickedPost.body = "Updated body"
adapter.notifyItemChanged(position)
}
override fun onDeletePost(position: Int) {
dummyList.removeAt(position)
adapter.notifyItemRemoved(position)
}
}
Here is how my TempConverterFragment looks like:
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.example.MainActivity
import com.example.projectdrivemark.R
import com.example.projectdrivemark.databinding.FragmentTempConverterBinding
class TempConverterFragment: Fragment(){
private lateinit var binding: FragmentTempConverterBinding
val celsiusButton = binding.celsiusButton
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = inflater.inflate(R.layout.fragment_temp_converter, container, false)
celsiusButton.setOnClickListener {
celsiusFunction(celsiusButton)
}
return binding.rootView
}
fun celsiusFunction(view: View){
val fahrenheitView = binding!!.userTemp
val fahrenheitValue = fahrenheitView.text.toString()
if(!fahrenheitValue.isBlank()){
val celsiusCovertedValue = (fahrenheitValue.toDouble() - 32) * 5/9
val celsiusValue = String.format("%.2f", celsiusCovertedValue)
Toast.makeText(activity,
"$fahrenheitValue fahrenheit is $celsiusValue degrees celsius",
Toast.LENGTH_LONG).show()
}else {
Toast.makeText(activity, "You must enter a value to convert", Toast.LENGTH_LONG).show()
}
}
fun farenheitFunction(view: View){
val celsiusView = binding.userTemp
val celsiusValue = celsiusView.text.toString()
if(!celsiusValue.isBlank()){
val farenheitConvertedValue = celsiusValue.toDouble() * 9/5 + 32
val farenheitValue = String.format("%.2f", farenheitConvertedValue)
Toast.makeText(activity,
"$celsiusValue degrees celsius is $farenheitValue farenheit",
Toast.LENGTH_LONG).show()
}else{
Toast.makeText(activity, "You must enter a value to convert", Toast.LENGTH_LONG).show()
}
}
}
And here is how my Xml Fragment looks like:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="487dp"
android:layout_height="320dp"
android:layout_marginBottom="16dp"
android:adjustViewBounds="true"
android:cropToPadding="false"
android:scaleType="fitXY"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/termometer" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="62dp"
android:layout_marginLeft="62dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="76dp"
android:layout_marginRight="76dp"
android:text="Enter desired temperature to convert"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<EditText
android:id="@+id/userTemp"
style="@android:style/Widget.DeviceDefault.EditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="140dp"
android:layout_marginLeft="140dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="140dp"
android:layout_marginRight="140dp"
android:ems="10"
android:hint="Enter Temperature Here"
android:inputType="numberDecimal"
android:selectAllOnFocus="false"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/celsiusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="32dp"
android:onClick="celsiusFunction"
android:text="to Celsius"
app:backgroundTint="@color/purple_200"
app:layout_constraintEnd_toStartOf="@+id/farenheitButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/userTemp" />
<Button
android:id="@+id/farenheitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="41dp"
android:layout_marginLeft="41dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="72dp"
android:layout_marginRight="72dp"
android:onClick="farenheitFunction"
android:text="to Farenheit"
app:backgroundTint="@color/teal_200"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/celsiusButton"
app:layout_constraintTop_toBottomOf="@+id/userTemp" />
</androidx.constraintlayout.widget.ConstraintLayout>
How to initialize a lateinit binding? Or is it better just use view.findViewById?
Solution
remove the 'val' before binding in your onCreatView in your fragment. You have already declared it and initialise it like below
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
binding = FragmentTempConverterBinding.inflate(inflater, container, false)
return binding.root
}
Answered By - Greeshma
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.