Access layout widget using synthetic reference in DialogFragment

Hello
The layout have single DatePicker widget with datePicker id

I wonder about usage of synthetic references generated by kotlin-android-extensions
As I understand I should have access to datePicker reference anywere in the class (especially Location1, and Location2). Android Studio see references correctly (no errors, I can properly jump to declaration, I have proper code hit), but when running this peace of code I got error:
java.lang.IllegalArgumentException: Parameter specified as non-null is null

import android.app.Dialog
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import kotlinx.android.synthetic.main.dialog_date.*

class DatePickerFragment() : DialogFragment() {
//    private lateinit var datePicker: DatePicker
    
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val v = LayoutInflater.from(activity)
                .inflate(R.layout.dialog_date, null)

//       datePicker = v.findViewById(R.id.datePicker) as DatePicker
            var alert = AlertDialog.Builder(activity)
           // Location1: cannot access datePicker error here unless i uncomment findViewById
        with(alert)
        {
            setView(v)
            setTitle(R.string.date_picker_title)
            setPositiveButton(android.R.string.ok) { dialog, witchButton -> onPositiveClick() }
        }

        return alert.create()
    }

    private fun onPositiveClick() {
        println(datePicker) // Location2: cannot access datePicker error here
    }
}

This works fine when I uncomment findViewById and datePicker variable declaration lines, but I believe this should work without this (as I understood this is the job kotlin android extensions does)
I missing something? How to make it work wiftout using findViewById?

1 Like

I had the same problem.
I think maybe it’s because the Fragment originally needed to bind the View in the ‘OnCreateView,’ so you have to in the ‘OnViewCreated’ or later to get the bound View.

Since I figured out a sorta-way around this and this is the only useful hit when googling the problem… You can call synthetic properties on a specified view, so if you stash the view as a class variable like so:

 import android.app.Dialog
 import android.os.Bundle
 import android.support.v4.app.DialogFragment
 import android.support.v7.app.AlertDialog
 import android.view.LayoutInflater
 import kotlinx.android.synthetic.main.dialog_date.*
 
class DatePickerFragment() : DialogFragment() {
 //    private lateinit var datePicker: DatePicker
    private lateinit var mView

     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         mView = LayoutInflater.from(activity)
                 .inflate(R.layout.dialog_date, null)

 //       datePicker = v.findViewById(R.id.datePicker) as DatePicker
             var alert = AlertDialog.Builder(activity)
            // Location1: cannot access datePicker error here unless i uncomment findViewById
         with(alert)
         {
             setView(mView)
             setTitle(R.string.date_picker_title)
             setPositiveButton(android.R.string.ok) { dialog, witchButton -> onPositiveClick() }
         }
 
         return alert.create()
     }
 
     private fun onPositiveClick() {
         println(mView.datePicker) // Location2: access datePicker as property of mView here
     }
 }
2 Likes