Search code examples
javaandroidkotlinactivity-lifecycleuser-preferences

userPreferences acting weird, not saving or retrieving all key-values, what am I doing wrong?


I have an ultra simple calculator which outputs some numbers to 4 separate labels. It is essential to the users experience that the labels hold data over app kills, back button, etc.

Currently I have userPreferences setup as per instructions. It seems super simple but when returning to the activity screen in different situations all labels contain the same number as only one of the labels. Example:

Actual:

label 1: 90
label 2: 90
label 3: 90
label 4: 90

Expected:

label 1: 90
label 2: 2030
label 3: 40654
label 4: *list of calculations from above numbers*

I have tried various combinations of retrieving the data from override fun onResume, onStart, onRestart as well as saving in onStop, onPause, onDestroy etc... Nothing worked, still same output as above.

EDIT: on a positive note, user preferences is indeed saving that one single label data throughout all lifecycle situations...

Here is my code as it stands now with none of the activity lifecycle attempts:

class Calc : AppCompatActivity() {

@RequiresApi(Build.VERSION_CODES.KITKAT)
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    this.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT //Set Portrait only
    setContentView(R.layout.activity_calc)

    // Instantiate SharedPreferences for saving user input
    val pref: SharedPreferences = applicationContext.getSharedPreferences("MyPref", 
MODE_PRIVATE) ?: return // Call to assign saved value
    val editor: SharedPreferences.Editor = pref.edit() // Call editor. to save to file

    // Retrieve saved data if it exists
    if (pref.contains(UNIT) &&
        pref.contains(VOLUME) &&
        pref.contains(HEIGHT) &&
        pref.contains(CALCULATION)) {
        unit.text = pref.getString(UNIT, "")
        volume.text = pref.getString(VOLUME, "")
        height.text = pref.getString(HEIGHT, "")
        calculation.text = pref.getString(CALCULATION, "")
    }

    val popup = Utilities
    // Declare calculate button and call function to crunch numbers and output them
    calculateButton.setOnClickListener {

        hideKeyboard() // Hide keyboard on button press
        editor.clear() // Clears saved data

//
// Bunch of calculator code that assigns numbers to 4 output labels...
//

            // Save data to sharedPreferences
            editor.putString(UNIT, outputUnit.text.toString())
            editor.putString(VOLUME, outputVolume.text.toString())
            editor.putString(HEIGHT, outputHeight.text.toString())
            editor.putString(CALCULATION, outputCalculation.text.toString())
            editor.apply() // Finalizes save asynchronously
        }
    }
}

Instanced in a .Kt file:

const val UNIT = ""
const val VOLUME = ""
const val HEIGHT = ""
const val CALCULATION = ""

Solution

  • The key values you pass to save and retrieve your data in sharedpreferences are identical... each is an empty string

    ""

    const val UNIT = ""
    const val VOLUME = ""
    const val HEIGHT = ""
    const val CALCULATION = ""
    

    Each key must be unique and contain an actual string value that can be retrieved against:

    const val UNIT = "UNIT"
    const val VOLUME = "VOLUME"
    const val HEIGHT = "HEIGHT"
    const val CALCULATION = "CALCULATION"
    

    Since the values retrieved are integers not strings then why not store them as integers?

    pref.getInt(UNIT, 0)
    
    editor.putInt(UNIT, outputUnit.text.toString().toInt())