12

As the title suggests Im getting a red underline under "id" on the line "var myNote = Note(id, title, note, ServerValue.TIMESTAMP)" Error "Required:String Found:String?" Kotlin and Android Studio

class MainActivity : AppCompatActivity() {
    var mRef:DatabaseReference? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val database = FirebaseDatabase.getInstance()
        mRef = database.getReference("Notes")

        add_new_note.setOnClickListener {
            showDialogAddNote()
        }
    }

    fun showDialogAddNote() {
        val alertBuilder = AlertDialog.Builder(this)

        val view = layoutInflater.inflate(R.layout.add_note, null)

        alertBuilder.setView(view)

        val alertDialog = alertBuilder.create()
        alertDialog.show()

        view.btnSaveNote.setOnClickListener {
            val title = view.etTitle.text.toString()
            val note = view.etNote.text.toString()

            if (title.isNotEmpty() && note.isNotEmpty()) {
                var id = mRef!!.push().key

                var myNote = Note(id, title, note, ServerValue.TIMESTAMP)
                mRef!!.child(id).setValue(myNote)
                alertDialog.dismiss()    
            } else {
                Toast.makeText(this, "Empty", Toast.LENGTH_LONG).show()
            }
        }
    }
}

Here is my Notes.kt class

package com.example.gearoidodonovan.books

import java.util.*

class Note (var id:String, var title:String, var note:String, var timestamp: MutableMap<String, String>) {
}
juanlumn
  • 6,155
  • 2
  • 30
  • 39
Gearoid O Donovan
  • 127
  • 1
  • 1
  • 3
  • 1
    Your issue is conceptually equivalent to: https://stackoverflow.com/questions/36465626/kotlin-required-kotlin-boolean-found-kotlin-boolean – user2340612 Jan 22 '19 at 17:14
  • `lateinit var mRef:DatabaseReference` helps to avoid !! around mRef. The `mRef!!.push().key` can be null. It is up to your database to understand if it is possible or not. The safest way is to add a check for null, e,g, if statement or to use Elvis operator `?:` to pass an expression when the left side is null – Eugene Petrenko Jan 22 '19 at 21:52

3 Answers3

14

Kotlin forces you to be hyper-conscious about nullability.

Your Note entity say its requires a non-nullable id:String, and apparently, mRef!!.push().key returns a String? meaning it's a nullable String. You can fix this by double-banging it , i.e. mReff!!.push().key!!

Another tip is to ALT+ENTER these Kotlin related errors, it'll provide the double-bang for you.

em_
  • 2,134
  • 2
  • 24
  • 39
2

Your id property in Note is declared as non-null String, while the key you have is a potentially null String?. You need to bridge this gap.

  1. The simplest but most dangerous way is to use !!, which will produce an exception if the key was null, i.e.

    var id = mRef!!.push().key!!
    
  2. A better way is to handle the null case somehow, for example by performing a null check:

    var id = mRef!!.push().key
    if (id != null) {
        var myNote = Note(id, title, note, ServerValue.TIMESTAMP)
        mRef!!.child(id).setValue(myNote)
        alertDialog.dismiss()
    } else {
        // handle the case where key is null somehow
    }
    
  3. You could also make the property in your own class nullable, and deal with the ID value in there potentially being null later:

    class Note (var id: String?, var title: String, var note: String, var timestamp: MutableMap<String, String>)
    

Note that all the mRef!! calls are problematic as well. For one, Hungarian notation (the m prefix) is generally discouraged in Kotlin, and the !! operator is dangerous as well. You'd be better off handling the null case early for that reference, and then you could use it more conveniently, without having to litter your code with !!.

I also encourage you to read up on null safety in general the official documentation or in this answer.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • 2
    "..`!!` is dangerous.." - it's important to keep in mind that while yes you should be conscious of the nullable scenarios, there is something to be said in specific situations (maybe not this example) where something should really _never_ be null even though the return type can be - then there are bigger problems at hand -maybe the app should kick and scream until the workflow issue is solved. – em_ Jan 22 '19 at 16:00
  • I've set to see a legitimately safe use of this operator outside of singleton initialization when parameters are required. No matter where you assume it's safe to use, it _will_ come back to bite you. – zsmb13 Jan 22 '19 at 16:27
0

You can use:

@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203