#android #kotlin
#Android #kotlin
Вопрос:
Fragment
Сбой onClick с ошибкой ниже
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414)
at android.view.View.performClick(View.java:7357)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:7334)
at android.view.View.access$3600(View.java:808)
at android.view.View$PerformClick.run(View.java:28200)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
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: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:7357)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:7334)
at android.view.View.access$3600(View.java:808)
at android.view.View$PerformClick.run(View.java:28200)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
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: java.lang.NullPointerException: farenheitView must not be null
at com.example.MainActivity.celsiusFunction(MainActivity.kt:68)
MainActivity:
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)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val tempConverter = TempConverterFragment()
val recyclerView = RecyclerViewFragment()
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
val uploaderView = UploaderFragment(this)
setFragmentView(recyclerView)
binding.bottomNavBar.setOnNavigationItemSelectedListener {
when(it.itemId){
R.id.listView -> setFragmentView(recyclerView)
R.id.tempConverterView -> setFragmentView(tempConverter)
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)
}
fun celsiusFunction(view: View){
val farenheitView = view.findViewById<EditText>(R.id.userTemp)
val farenheitValue = farenheitView.text.toString()
if(!farenheitValue.isBlank()){
val celsiusCovertedValue = (farenheitValue.toDouble() - 32) * 5/9
val celsiusValue = String.format("%.2f", celsiusCovertedValue)
Toast.makeText(this,
"$farenheitValue fahrenheit is $celsiusValue degrees celsius",
Toast.LENGTH_LONG).show()
}else {
Toast.makeText(this, "You must enter a value to convert", Toast.LENGTH_LONG).show()
}
}
fun farenheitFunction(view: View){
val celsiusView = view.findViewById<EditText>(R.id.userTemp)
val celsiusValue = celsiusView.text.toString()
if(!celsiusValue.isBlank()){
val farenheitConvertedValue = celsiusValue.toDouble() * 9/5 32
val farenheitValue = String.format("%.2f", farenheitConvertedValue)
Toast.makeText(this,
"$celsiusValue degrees celsius is $farenheitValue farenheit",
Toast.LENGTH_LONG).show()
}else{
Toast.makeText(this, "You must enter a value to convert", Toast.LENGTH_LONG).show()
}
}
}
И вот мой класс tempConverter:
class TempConverterFragment: Fragment(){
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = inflater.inflate(R.layout.fragment_temp_converter, container, false)
return binding
}
}
Вот мой MainActivity
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.MainActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@ id/bottomNavBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<FrameLayout
android:id="@ id/main_fragment_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@ id/bottomNavBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Вот где я реализую свою TempConverter
функцию:
<?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.constraintlayout.виджет.ConstraintLayout>
Таким образом, мой макет приложения имеет BottomNavBar
. И у каждой панели навигации есть свой собственный фрагмент. Одним из них является a RecyclerView
, a TempConverter
view и ImageUploader
view. Как правильно реализовать действие фрагмента и что не так с моим кодом?
Комментарии:
1. Привет, как я вижу из вашего logcat, вы получаете свое
fahrenhit
представление как нулевое. Видите эти строки :-Caused by: java.lang.NullPointerException: farenheitView must not be null at com.example.MainActivity.celsiusFunction(MainActivity.kt:68)
2. Я предполагаю, что строка номер 68 в вашей
mainActivity
строке — это следующие строки: —val farenheitView = view.findViewById<EditText>(R.id.userTemp) val farenheitValue = farenheitView.text.toString()
откуда вы вызываете эту функцию?3. Я вызываю это из своего основного класса
4. Пожалуйста, добавьте этот код, я не вижу его в вашем
MainActivity
, также, пожалуйста, проверьте, используете ли вы то жеid
xml
самое и в своем. это должны бытьuserTemp
оба варианта5. Я добавил код основного класса выше в функцию celsius() . Я снова проверю свой идентификатор
Ответ №1:
из logcat вы можете видеть, что в нем указано, что ваше значение farenheitView
равно нулю, и это не вызывает ошибку. Теперь, согласно xml
и вашему MainActivity
, ясно, что у вас есть свой farenheitView
в вашем fragment
, но вы пытаетесь получить это в своем MainActivity
, что является причиной, по которой вы получаете null
там значение.
Вместо этого вам нужно сделать так, чтобы ваши функции фрагментов находились только внутри вашего fragment
класса, а не в вашем mainActivity
классе, и вы можете вызывать их везде, где вам это нужно fragment
.
Также я бы посоветовал вам использовать bindings
в вашем fragments
, а также, как я вижу, вы уже использовали это в своем mainActivity
.
Вы можете узнать больше об этом Fragments
здесь и здесь (также есть множество других блогов и руководств).
Счастливого кодирования!