Why does accessing TextView from within onTimeSet() function produces a runtime error?

157 Views Asked by At

I've just started learning Android development using Kotlin and ran into this error.

I followed this guide to create some basic time and date picker dialogues which are triggered through their respective button presses. Here is a code snippet of the TimePickerFragment class for the reference:

class TimePickerFragment : DialogFragment(), TimePickerDialog.OnTimeSetListener {


override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    // Use the current time as the default values for the picker
    val c = Calendar.getInstance()
    val hour = c.get(Calendar.HOUR_OF_DAY)
    val minute = c.get(Calendar.MINUTE)


    // Create a new instance of TimePickerDialog and return it
    return TimePickerDialog(activity, this, hour, minute, DateFormat.is24HourFormat(activity))
}

override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) {
    //
    // Do something with the time chosen by the user
    timeSet = true
    //val timeText = findViewById<TextView>(R.id.timeView)
    //timeView.text = getString(R.string.time_str, hourOfDay, minute)
    timeStr = "$hourOfDay : $minute"
    //timeView.setText(timeStr)

}

So, as you might have noticed in the code above, I've been struggling with the onTimeSet() function. What I wish to do is to update a TextView's current text with the time user just selected. However, at runtime when I press OK, the app crashes.

Is it illegal to do that in Kotlin? How else can this be done?

edit:

logcat crash report:

2020-12-13 05:24:28.831 5480-5480/com.example.myproject E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myproject, PID: 5480
java.lang.IllegalStateException: timeView must not be null
    at com.example.myproject.TimePickerFragment.onTimeSet(MainActivity2.kt:81)
    at android.app.TimePickerDialog.onClick(TimePickerDialog.java:172)
    at android.app.TimePickerDialog$1.onClick(TimePickerDialog.java:154)
    at android.view.View.performClick(View.java:6608)
    at android.view.View.performClickInternal(View.java:6585)
    at android.view.View.access$3100(View.java:782)
    at android.view.View$PerformClick.run(View.java:25945)
    at android.os.Handler.handleCallback(Handler.java:874)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:198)
    at android.app.ActivityThread.main(ActivityThread.java:6729)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
1

There are 1 best solutions below

3
Iván Garza Bermea On

Following the question + comments, it seems that you're trying to access a TextView that belongs to your Activity inside the TimePickerFragment and that's just not going to work. Instead, you need to pass back the significant data to your Activity, and only then attempt to change your TextView.

A very easy way of doing this, for example, is to have in your Activity a public method

fun setTime(timeStr: String) {
    timeView.text = timeStr
}

which your TimePickerFragment could access directly by calling

(requireActivity() as YourActivity).setTime(...)

as soon as onTimerSet(..) is called through the listener.

Of course, there are many other ways of communicating with your Activity like sending back a result so you'll have to see what works better with your system.