1

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)
Chucky
  • 41
  • 5
  • 3
    please post the logcat crash report – Zain Dec 12 '20 at 23:56
  • 1
    "What I wish to do is to update a TextView's current text with the time user just selected" -- this fragment does not have that `TextView`. Something else does. You need to get your data to whatever has that `TextView`. – CommonsWare Dec 12 '20 at 23:58
  • 1
    @Zain Sorry but how do I do that? – Chucky Dec 13 '20 at 00:14
  • 1
    @CommonsWare Yup, the 'TextView' is in the activity by which this fragment is being created. – Chucky Dec 13 '20 at 00:18
  • 1
    When you run on a device conncted to Android studio.. There's a Logcat tab at the bottom toolbar contains several types of logs including errors – Zain Dec 13 '20 at 00:23
  • @Chucky You should get your data from the `MainActivity` itself or you need a `TextView` in the `Fragment` to get the desired output – Vishnu Dec 13 '20 at 00:24
  • @Zain did that, edited the post – Chucky Dec 13 '20 at 00:32
  • @Chucky Did you call `findViewById()` from `Fragment`? – Vishnu Dec 13 '20 at 00:34
  • @Vishnu So should I return the values of `hourOfDay` and `minute` to the main activity? How to do that? – Chucky Dec 13 '20 at 00:38
  • @Vishnu yes I did call `findViewById()` from fragment. That didn't work, so I imported `import kotlinx.android.synthetic.main.activity_main2.*` but this didn't work either – Chucky Dec 13 '20 at 00:40
  • @Chucky You can do everything from `MainActivity`. Am I right? Also, you had better not access views of `MainActivity` from `Fragment` – Vishnu Dec 13 '20 at 00:41
  • I mean, showing `Dialog` & `Overriding` methods from `MainActivity` itself... As in the documentation you mentioned – Vishnu Dec 13 '20 at 00:42

1 Answers1

1

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.

Ivan Garza
  • 553
  • 2
  • 14
  • Actually it's the other way around, the `TimePickerFragment` is inside the `Activity`. But I do get what you are saying. Only if you could elaborate on " `(requireActivity() as YourActivity).setTime(...)` " it would be really helpful. – Chucky Dec 13 '20 at 14:52
  • 2
    That's what Ivan's saying, you're trying to access a ``TextView`` that belongs to your ``Activity`` from inside the ``TimePickerFragment`` instead. The suggestion here is to give the parent activity a ``setTime`` method, then get the activity and call that method from inside the dialog. The method is inside the activity, so it can see the ``TextView`` inside the activity's layout – cactustictacs Dec 13 '20 at 15:22
  • @cactustictacs doing so made the app throw a `NullPointerException` T_T – Chucky Dec 13 '20 at 17:37