Home > Blockchain >  ".contains" returns null pointer exception even when the list has been initialised and the
".contains" returns null pointer exception even when the list has been initialised and the

Time:12-01

android studio screenshot

stack trace image

now working image

the above screen shot has the problem code and the todo comments will guide you to where the problem is. line 34 is the point of failure. I have tried the code with an empty list seperately in a different ide where it worked just fine. this was the code i tested that worked fine -

fun main() {
    val dList = mutableListOf<String>()
    val newString = "hello"
    if (dList.contains(newString)){
        print("contains")
    }else{
        print("does not contain")
    }
}

so, the empty list isn't the problem. I also tried copy pasting the code from the tutorial I am following [I am currently learning android studio basics in kotlin] that didn't work either. I don't even know what to try anymore. I even searched the error on here. it was for java with a initialisation issue. mine does not have that. just to be on the safe side, I went through the previous steps again too see if I missed something. didn't find anything. So, I'm stuck. the code from the screen shot is given below [also includes commented out code] -

package com.example.android.unscramble.ui.game

import android.util.Log
import androidx.lifecycle.ViewModel

class GameViewModel : ViewModel() {
    val TAG = "GameViewModel"

    init {
        Log.d(TAG, "View Model initialised")
        getNextWord()
    }
    private var _score = 0
    private var _currentWordCount = 0
    private lateinit var _currentScrambledWord: String
    val currentScrambledWord: String get() = _currentScrambledWord
    private var wordsList: MutableList<String> = mutableListOf()
    lateinit var currentWord: String

    override fun onCleared() {
        super.onCleared()
        Log.d("GameViewModel", "game view model destroyed")
    }

    private fun getNextWord() {
        currentWord = allWordsList.random()     //todo - is getting assigned
        Log.d(TAG,"current word = ${currentWord}")  //todo - current word isn't null
        val tempWord = currentWord.toCharArray()
        tempWord.shuffle()
        while (String(tempWord).equals(currentWord, false)) {
            tempWord.shuffle()
        }
        Log.d(TAG,"point - 1")  //todo - gets executed
        if (wordsList.contains(currentWord)){       //todo - point of failure
            Log.d(TAG,"point - 2")      //todo - not getting executed
            getNextWord()
        } else {
            Log.d(TAG,"point - 3")      //todo - not getting executed
            _currentScrambledWord = String(tempWord)
              _currentWordCount
            wordsList.add(currentWord)
        }
    }//todo - there isn't anything executable below. all commented out
    /*
    fun getNextWord() {
        currentWord = allWordsList.random()
        Log.d(TAG, "current word = ${currentWord}")
        if (wordsList.contains(currentWord)) {
            Log.d(TAG, "step - 1")
            getNextWord()
        }
        else {
            Log.d(TAG, "step - 2")
            val tempWord = currentWord.toCharArray()
            while (String(tempWord) == currentWord) {
                tempWord.shuffle()
            }
            Log.d(TAG, "step - 3")
            wordsList.add(currentWord)
            _currentScrambledWord = String(tempWord)
            _currentWordCount  
        }
    }
    */
}

CodePudding user response:

I believe this is happening because of the ordering of your code, with the init block executing before other variables have been initialized. if you were to move the init block to a method:

fun foo() {
   Log.d(TAG, "View Model initialised")
   getNextWord()
}

and just calling foo after you've created an instance of your view model, that should hopefully fix the problem.

Alternatively, moving the declaration of variables before the init block would probably also work.

similar type of question, i suppose, here

  • Related